public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] gen_atmel_mci freeze on at91sam9g45
@ 2010-12-04 17:08 eric cariat
  2010-12-05  8:30 ` Reinhard Meyer
  0 siblings, 1 reply; 4+ messages in thread
From: eric cariat @ 2010-12-04 17:08 UTC (permalink / raw)
  To: u-boot

Hi,

I'm currently working on a custom board with an at91sam9g45 : I followed the
instruction in README.atmel_mci. In U-boot, if I use the command mmcinfo,
the system hang. The uSD is working correctly with at91bootstrap and linux.
In U-boot everything seems fine, the card exchange a few command and
response, and then freeze on the command 55 51 (the first command that will
receive some data on DAT0 ) :

U-Boot> mmcinfo
mci: bus_hz is 133333333, setting clock 150000 Hz, block size 512
mci: setting clock 260416 Hz, block size 512
mci: bus_hz is 133333333, setting clock 0 Hz, block size 512
mci: setting clock 260416 Hz, block size 512
mci: bus_hz is 133333333, setting clock 260416 Hz, block size 512
mci: setting clock 260416 Hz, block size 512
gen_atmel_mci: CMDR 00001000 ( 0) ARGR 00000000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001048 ( 8) ARGR 000001aa (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001077 (55) ARGR 00000000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001069 (41) ARGR 40300000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001077 (55) ARGR 00000000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001069 (41) ARGR 40300000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001082 ( 2) ARGR 00000000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001043 ( 3) ARGR 00000000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001089 ( 9) ARGR 88f70000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 000010c7 ( 7) ARGR 88f70000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00001077 (55) ARGR 88f70000 (SR: 00000000) DEBUG
gen_atmel_mci: CMDR 00051073 (51) ARGR 00000000 (SR: 00000000) DEBUG
Read Data:
00000000: 02 25 00 00 00 00 00 00    .%......
filling rest of block...

then everything freeze ...
But if I add some printf to debug , just after the
mci_data_op=mci_data_read() in gen_atmel_mci, then everything is OK and I
can now use the uSD without any problem.
Here is where I add the printf, so uSD is correctly handled :

diff -crbN u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c
u-boot-2010.09/drivers/mmc/gen_atmel_mci.c
*** u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c    2010-09-28
23:20:55.000000000 +0200
--- u-boot-2010.09/drivers/mmc/gen_atmel_mci.c    2010-12-04
17:52:59.092770689 +0100
***************
*** 252,257 ****
--- 252,258 ----
              while (!status && word_count < (sys_blocksize / 4)) {
                  status = mci_data_op(mci, &dummy,
                      error_flags);
+                 printf("status=%x\n",status);
                  word_count++;
              }
              if (status) {

 The result (status) from mci_data_op (=mci_data_read()) is always 0.  It's
a bit like if there was a timeout not correctly handled. I had the same
sympton on different uSD. Actually U-boot is started by At91Bootstrap, so
some HMCI register are probably not@there default value ?
Any advice to investigate further ?

best regards,

Eric Cariat

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] gen_atmel_mci freeze on at91sam9g45
  2010-12-04 17:08 [U-Boot] gen_atmel_mci freeze on at91sam9g45 eric cariat
@ 2010-12-05  8:30 ` Reinhard Meyer
  2010-12-07 17:23   ` eric cariat
  0 siblings, 1 reply; 4+ messages in thread
From: Reinhard Meyer @ 2010-12-05  8:30 UTC (permalink / raw)
  To: u-boot

Dear eric cariat,
> I'm currently working on a custom board with an at91sam9g45 : I followed the
> instruction in README.atmel_mci. In U-boot, if I use the command mmcinfo,
> the system hang. The uSD is working correctly with at91bootstrap and linux.
> In U-boot everything seems fine, the card exchange a few command and
> response, and then freeze on the command 55 51 (the first command that will
> receive some data on DAT0 ) :
> 
> U-Boot> mmcinfo
> mci: bus_hz is 133333333, setting clock 150000 Hz, block size 512
"setting clock" should read "requesting clock". 150000 is the clock a MMC card
should be inquired with. Unfortunately the minimum clock obtainable is 260416,
but that did not cause problems with SD cards so far...
> mci: setting clock 260416 Hz, block size 512
So the software sets it to the minimum-.
> mci: bus_hz is 133333333, setting clock 0 Hz, block size 512
> mci: setting clock 260416 Hz, block size 512
> mci: bus_hz is 133333333, setting clock 260416 Hz, block size 512
> mci: setting clock 260416 Hz, block size 512

First make sure the clock values are correct: Assuming the system is running
at 400MHz, this would make sense if the MCI is clocked by system clock / 3.
Then the minimum clock would indeed be 260416.

Is the 9G45 (H)MCI is really identical to the 9260 MCI or are there subtle
differences?

> But if I add some printf to debug , just after the
> mci_data_op=mci_data_read() in gen_atmel_mci, then everything is OK and I
> can now use the uSD without any problem.
> Here is where I add the printf, so uSD is correctly handled :
> 
> diff -crbN u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c
> u-boot-2010.09/drivers/mmc/gen_atmel_mci.c
> *** u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c    2010-09-28
> 23:20:55.000000000 +0200
> --- u-boot-2010.09/drivers/mmc/gen_atmel_mci.c    2010-12-04
> 17:52:59.092770689 +0100
> ***************
> *** 252,257 ****
> --- 252,258 ----
>               while (!status && word_count < (sys_blocksize / 4)) {
>                   status = mci_data_op(mci, &dummy,
>                       error_flags);
> +                 printf("status=%x\n",status);
>                   word_count++;
>               }
>               if (status) {
> 

Have you tested whether a udelay() serves the same purpose? It would seem that there is
an issue when mci_data_op() is called too frequently. However, quite the same code exists
a few lines above and it did not hang there.

Is your data cache on?

There are no timeouts coded in mci_data_read() and mci_data_write(), maybe it would be good
to add some...

I also cannot rule out that pre-initialisation of the MCI by the bootstrap code could leave
some registers with values that the gen_atmel_mci driver does not reset. But then, a printf
would unlikely fix the problem.

Patches are always welcome ;)

Best Regards,
Reinhard

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] gen_atmel_mci freeze on at91sam9g45
  2010-12-05  8:30 ` Reinhard Meyer
@ 2010-12-07 17:23   ` eric cariat
  2010-12-08 20:15     ` Reinhard Meyer
  0 siblings, 1 reply; 4+ messages in thread
From: eric cariat @ 2010-12-07 17:23 UTC (permalink / raw)
  To: u-boot

Hi Rheinard,

2010/12/5 Reinhard Meyer <u-boot@emk-elektronik.de>

> Dear eric cariat,
> > I'm currently working on a custom board with an at91sam9g45 : I followed
> the
> > instruction in README.atmel_mci. In U-boot, if I use the command mmcinfo,
> > the system hang. The uSD is working correctly with at91bootstrap and
> linux.
> > In U-boot everything seems fine, the card exchange a few command and
> > response, and then freeze on the command 55 51 (the first command that
> will
> > receive some data on DAT0 ) :
> >
> > U-Boot> mmcinfo
> > mci: bus_hz is 133333333, setting clock 150000 Hz, block size 512
> "setting clock" should read "requesting clock". 150000 is the clock a MMC
> card
> should be inquired with. Unfortunately the minimum clock obtainable is
> 260416,
> but that did not cause problems with SD cards so far...
> > mci: setting clock 260416 Hz, block size 512
> So the software sets it to the minimum-.
> > mci: bus_hz is 133333333, setting clock 0 Hz, block size 512
> > mci: setting clock 260416 Hz, block size 512
> > mci: bus_hz is 133333333, setting clock 260416 Hz, block size 512
> > mci: setting clock 260416 Hz, block size 512
>
> First make sure the clock values are correct: Assuming the system is
> running
> at 400MHz, this would make sense if the MCI is clocked by system clock / 3.
> Then the minimum clock would indeed be 260416.
>

Clock values are OK (running from 12 Mhz like the 9g45 eval kit), system
running at 400 Mhz.
260416 Hz is exactly what I probe on the hardware.


>
> Is the 9G45 (H)MCI is really identical to the 9260 MCI or are there subtle
> differences?
>

I checked the datasheet of the 9260, most register seems to be the same...
I suppose you have been testing the gen_atmel_mci on the 9260 ?

>
> > But if I add some printf to debug , just after the
> > mci_data_op=mci_data_read() in gen_atmel_mci, then everything is OK and I
> > can now use the uSD without any problem.
> > Here is where I add the printf, so uSD is correctly handled :
> >
> > diff -crbN u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c
> > u-boot-2010.09/drivers/mmc/gen_atmel_mci.c
> > *** u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c    2010-09-28
> > 23:20:55.000000000 +0200
> > --- u-boot-2010.09/drivers/mmc/gen_atmel_mci.c    2010-12-04
> > 17:52:59.092770689 +0100
> > ***************
> > *** 252,257 ****
> > --- 252,258 ----
> >               while (!status && word_count < (sys_blocksize / 4)) {
> >                   status = mci_data_op(mci, &dummy,
> >                       error_flags);
> > +                 printf("status=%x\n",status);
> >                   word_count++;
> >               }
> >               if (status) {
> >
>
> Have you tested whether a udelay() serves the same purpose? It would seem
> that there is
> an issue when mci_data_op() is called too frequently. However, quite the
> same code exists
> a few lines above and it did not hang there.
>
>
I added a udelay(1) and udelay(50) -> it freeze
If I put a udelay(100) -> everything is OK (same effect as printf)


> Is your data cache on?
>

I suppose it is enabled by default, so I added #define
CONFIG_SYS_NO_CP15_CACHE in my config file -> but that still freeze

>
> There are no timeouts coded in mci_data_read() and mci_data_write(), maybe
> it would be good
> to add some...
>
> I also cannot rule out that pre-initialisation of the MCI by the bootstrap
> code could leave
> some registers with values that the gen_atmel_mci driver does not reset.
> But then, a printf
> would unlikely fix the problem.
>
> Patches are always welcome ;)
>
> Best Regards,
> Reinhard
>
>
My observation are the following :

It seems that we are trying to read too many data byte : for ACMD 51 : the
data reply is not a full 512 bytes data packet, but only 8 bytes len
(checked with oscillo). Actually when in function mci_send_cmd() with ACMD
51, we first read the 8 "useful" byte ... then we try to "fill the rest of
block" => we try to read 512 - 8 = 504 more bytes  (which never comes on the
DAT0 )
as there are no more data we should exit from mci_data_read() with a timeout
error, but this never happen (I have to check error_flags about that)

Doing a pause or printf in the while change the RXRDY flag (set to 1) and so
we exit from the while without any error... ( I could not understand why ?
). It seems that when we don't read the correct number of byte, the MCI
controller behave incorrectly (the status register seems to be incoherent)

Actually the driver set a block len of 512 byte only once (at
initialization) in the mode register (mr) in gen_atmel_mci:mci_set_mode().
So I suppose we need to change dynamically the block len for each command
(most command will use the 512 byte data block reply, but some (like ACMD51)
are using a specific len -> I think we don't need to change the block len in
the SDCard see comment [1] below )

So I made the following change, ( just for information ) :

diff -crbN u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c
u-boot-2010.09/drivers/mmc/gen_atmel_mci.c
*** u-boot-2010.09.orig/drivers/mmc/gen_atmel_mci.c    2010-09-28
23:20:55.000000000 +0200
--- u-boot-2010.09/drivers/mmc/gen_atmel_mci.c    2010-12-07
18:14:05.956116190 +0100
***************
*** 174,179 ****
--- 174,180 ----
      u32 cmdr;
      u32 error_flags = 0;
      u32 status;
+     u32 mr;

      if (!initialized) {
          puts ("MCI not initialized!\n");
***************
*** 182,187 ****
--- 183,201 ----

      /* Figure out the transfer arguments */
      cmdr = mci_encode_cmd(cmd, data, &error_flags);
+     if (data)
+     {
+ #ifdef DEBUG
+         printf("data->blocksize = %d\n",data->blocksize);
+         printf(" mmc->write_bl_len = %d\n", mmc->write_bl_len);
+ #endif
+         /* get current mr register and change block size */
+         mr = readl(&mci->mr);
+         mr = mr & 0xffff;                   /* clear upper part */
+         mr = mr | (data->blocksize << 16);  /* set block size   */
+         writel( mr, &mci->mr);
+     }
+

      /* Send the command */
      writel(cmd->cmdarg, &mci->argr);
***************
*** 218,224 ****

          if (data->flags & MMC_DATA_READ) {
              mci_data_op = mci_data_read;
!             sys_blocksize = mmc->read_bl_len;
              ioptr = (u32*)data->dest;
          } else {
              mci_data_op = mci_data_write;
--- 232,239 ----

          if (data->flags & MMC_DATA_READ) {
              mci_data_op = mci_data_read;
!             /* sys_blocksize = mmc->read_bl_len; */
!             sys_blocksize = data->blocksize;
              ioptr = (u32*)data->dest;
          } else {
              mci_data_op = mci_data_write;

But this is not correct because it must be done only for specific command
(with a fixed data size  reply), Here, the "filling the rest of block" is
never used again -> the code is working using mmcinfo, rescan and fatls (I
d'ont need the printf or udelay anymore in the while loop), but
unfortunately If I remove all other debug information -> It freeze again !

So I suppose we have to modify the code for every command -> we need to know
if the data reply is a fixed size or if we have to fill the rest of loop (to
fill a 512 byte data packet). But the number of "data" byte reply for each
command is not really clear in the specification
("Simplified_Physical_Layer_Spec.pdf")
I don't know if there are some more documentation on that ...

I'm just thinking I have to check how this was done before gen_atmel_mci, in
an older U-Boot, maybe I can understand a little more...

I can see the gen_atmel_mci has been working on a V1.0 SDCARD :
http://www.mail-archive.com/u-boot at lists.denx.de/msg37774.html
so I checked with the V2.0 : I don't see any major difference (except a few
more register but SCR and ACMD51 are the same)

So I 'm not sure if I'm looking in the right direction ? am I missing
something about the length on data reply ?
just wanted to know what you think about all that ? any other advice ?

best regards,

Eric Cariat


For information I'm currently using an Sandisk 1 Gb uSD.


[1]  In
http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
pg 46 we can read for an other special function :
The block length is predefined to 512 bits and the use of SET_BLK_LEN
command is not necessary.
=> so we don't need to send BLK_LEN to the SDCard, but we need to inform the
at91 that the number of data will be 64 bytes, so it can calculate the CRC
and set it's flag according the new size.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [U-Boot] gen_atmel_mci freeze on at91sam9g45
  2010-12-07 17:23   ` eric cariat
@ 2010-12-08 20:15     ` Reinhard Meyer
  0 siblings, 0 replies; 4+ messages in thread
From: Reinhard Meyer @ 2010-12-08 20:15 UTC (permalink / raw)
  To: u-boot

Dear eric cariat,
>> First make sure the clock values are correct: Assuming the system is
>> running
>> at 400MHz, this would make sense if the MCI is clocked by system clock / 3.
>> Then the minimum clock would indeed be 260416.
>>
>
> Clock values are OK (running from 12 Mhz like the 9g45 eval kit), system
> running at 400 Mhz.
> 260416 Hz is exactly what I probe on the hardware.
Good.

>> Is the 9G45 (H)MCI is really identical to the 9260 MCI or are there subtle
>> differences?
>>
>
> I checked the datasheet of the 9260, most register seems to be the same...
> I suppose you have been testing the gen_atmel_mci on the 9260 ?

Correct, on 9xe which is like 9260

>> Have you tested whether a udelay() serves the same purpose? It would seem
>> that there is
>> an issue when mci_data_op() is called too frequently. However, quite the
>> same code exists
>> a few lines above and it did not hang there.
>>
>>
> I added a udelay(1) and udelay(50) ->  it freeze
> If I put a udelay(100) ->  everything is OK (same effect as printf)

100us is a significant slowdown, that means 10kWords per second...

>> Is your data cache on?
>>
>
> I suppose it is enabled by default, so I added #define
> CONFIG_SYS_NO_CP15_CACHE in my config file ->  but that still freeze

That define seems odd to me, it should be CONFIG_SYS_NO_DCACHE.

> My observation are the following :
>
> It seems that we are trying to read too many data byte : for ACMD 51 : the
> data reply is not a full 512 bytes data packet, but only 8 bytes len
> (checked with oscillo). Actually when in function mci_send_cmd() with ACMD
> 51, we first read the 8 "useful" byte ... then we try to "fill the rest of
> block" =>  we try to read 512 - 8 = 504 more bytes  (which never comes on the
> DAT0 )
> as there are no more data we should exit from mci_data_read() with a timeout
> error, but this never happen (I have to check error_flags about that)

That should not hurt, and even if, it should not depend on the speed at which
we are trying to read the dummy data.

>
> Doing a pause or printf in the while change the RXRDY flag (set to 1) and so
> we exit from the while without any error... ( I could not understand why ?
> ). It seems that when we don't read the correct number of byte, the MCI
> controller behave incorrectly (the status register seems to be incoherent)

This sounds very fishy to me.

>
> Actually the driver set a block len of 512 byte only once (at
> initialization) in the mode register (mr) in gen_atmel_mci:mci_set_mode().
> So I suppose we need to change dynamically the block len for each command
> (most command will use the 512 byte data block reply, but some (like ACMD51)
> are using a specific len ->  I think we don't need to change the block len in
> the SDCard see comment [1] below )
>

<snip>

> But this is not correct because it must be done only for specific command
> (with a fixed data size  reply), Here, the "filling the rest of block" is
> never used again ->  the code is working using mmcinfo, rescan and fatls (I
> d'ont need the printf or udelay anymore in the while loop), but
> unfortunately If I remove all other debug information ->  It freeze again !

Which again suggests its not due to the way the Card is handled.

> So I suppose we have to modify the code for every command ->  we need to know
> if the data reply is a fixed size or if we have to fill the rest of loop (to
> fill a 512 byte data packet). But the number of "data" byte reply for each
> command is not really clear in the specification
> ("Simplified_Physical_Layer_Spec.pdf")
> I don't know if there are some more documentation on that ...

Google for SDCard and license restrictions...

> So I 'm not sure if I'm looking in the right direction ? am I missing
> something about the length on data reply ?
> just wanted to know what you think about all that ? any other advice ?

I would think to look more in the hardware/memory/cache direction and less
in the driver direction. The 9xe/9260 here runs at 200MHz and the
MCI at 100 MHz, which is close to your 133MHz, and there are no such effects
here whatsoever from old 1GB Cards to 32GB SDHC Cards.

Best regards,
Reinhard

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-12-08 20:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-04 17:08 [U-Boot] gen_atmel_mci freeze on at91sam9g45 eric cariat
2010-12-05  8:30 ` Reinhard Meyer
2010-12-07 17:23   ` eric cariat
2010-12-08 20:15     ` Reinhard Meyer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox