Closed arahowerya closed 4 years ago
As it looks to me, your data lines have some errors... like no valid data could be received on the data lines when the bus is tested. If the CID is correctly read, it should mean that the CMD line works fine. The Extended CID is received as a data block of 512 bytes from what I remember (please correct me if I am wrong) So I would assume that the data lines are fine (at least DAT0) Can you try to hack the code to use just 1 data line and see if you can make it work ?
You are using SDMMC1 IP block right ?
All is left to do is to put a scope on the data lines and see what is happening, how the data is transmitted... if the switch function fails, then the card cannot go to a different mode. The switch function is the CMD6 that changes the condition of the card. Probably your fail is when it tries to go to 8 bit bus mode, then fallback to 4 bit, and then fallback to 1 bit. Try with 1bit from the starters see if that helps in any way
Also eMMCs are designed to operate at signaling/power at either 3v3, 1v8 or 1v2, it should not be changed during the operations. So 1V8sel does not have any point in your schematic. eMMC should not voltage switch. Are you using 3v3 for all voltage references for this eMMC ?
Thanks for your quick reply!
Looks to be 128 bits wide, and it matches what's in the datasheet. Is this the same as the extended CID?
I'll try and set it to use just 1 data line. I'm using SDMMC0.
We had a previous revision of the board that didn't have the 1v8 selection so we added it to this board to see if this was the issue. I can bridge it however to constantly select 1v8 or 3v3 so I'll try that too
I removed the switching voltage from 1v8 to 3v3 and tied all comms and pullups to 3v3.
I scoped the clock and DAT0 and got this. When it fails there are weird voltages present, goes into some odd impedance state, 1.3 1.4v?
The yellow trace is the clock, pink is DAT0
I added this debug code:
+++ b/driver/mci_media.c
@@ -591,6 +591,7 @@ static int mmc_cmd_switch_fun(struct sd_card *sdcard,
ret = host->ops->send_command(command, 0);
+ console_printf("mmc_cmd_switch_fun(access_mode = %d index = %d, value = %d) = %d\n", access_mode, index, value, ret);
sd_cmd_send_status(sdcard, retries);
if (ret)
return ret;
And got:
sd card identified with CID = 0xfe014e4d 0x4d433032 0x4742f707 0xf43c95ff
sdcard_identification success
MMC: Specification Version 4.0 or higher
MMC: v4.41 detected
MMC: highspeed supported
MMC: Dual Data Rate supported
mmc_cmd_switch_fun(access_mode = 3 index = 185, value = 1) = 0
MMC: detecting buswidth...
SDHC: Timeout waiting for command complete
mmc_cmd_switch_fun(access_mode = 3 index = 183, value = 2) = -10
SDHC: Timeout waiting for command complete
SDHC: Timeout waiting for command complete
mmc_cmd_switch_fun(access_mode = 3 index = 183, value = 1) = -10
SDHC: Timeout waiting for command complete
MMC: falling back to 1 bit bus width
SDHC: Timeout waiting for command complete
mmc_cmd_switch_fun(access_mode = 3 index = 183, value = 5) = -10
SDHC: Timeout waiting for command complete
MMC: DDR mode could not be enabled: -10
SDHC: Timeout waiting for command complete
*** FATFS: f_open, filename: [u-boot.bin]: error
SD/MMC: Failed to load image
So the function runs correctly once, and fails every other time?
switch_fun is used for various things throughout the initialization procedure. to switch to highspeed, to change bus width, etc. So it's normal that it's called multiple times. It looks like it starts failing that's true
Try to hack through mmc_detect_buswidth and see if that helps, skipping that detection should leave the emmc in 1 bit bus mode
Also, try to enable HIGH DRIVE STRENGTH for your eMMC pins... here is a wiki page that shows an example how to do that https://www.linux4sam.org/bin/view/Linux4SAM/SOM1EKeMMCSupport
Thanks for that. I hacked through mmc_detect_buswidth and got:
SDHC: Timeout waiting for command complete
mmc_cmd_switch_fun(access_mode = 3 index = 183, value = 5) = -1
SDHC: Timeout waiting for CMD and DAT Inhibit bits
SDHC: Timeout waiting for command complete
MMC: DDR mode could not be enabled: -1
SDHC: Timeout waiting for CMD and DAT Inhibit bits
SDHC: Timeout waiting for command complete
Changing the drive strength made no change. This is also like this on multiple boards.
remove the enabling of the DDR also. DDR only works with at least 4 bits so it will try to enable 4 bits again
basically you need mode 0 : 1 bit bus and no DDR
OK, did that and the errors disappeared! Thanks... However I cannot probe it in u-boot, nor can I write anything to it via sam-ba so I can't test if it's working. Apologies that this is vague! Should I concentrate on uboot?
So, did at91bootstrap succeed in copying u-boot from EMMC ??
I can't write anything to emmc to begin with. at91bootstrap is the only bit of software that vaguely recognizes its existence. I was hoping to find the problem in at91bootstrap
I can't write anything to emmc to begin with. at91bootstrap is the only bit of software that vaguely recognizes its existence. I was hoping to find the problem in at91bootstrap
I understand but it's very important if at91bootstrap managed to read on 1 bit or not. If 1 bit works, then, it's clear that the other 7 lines are messed up . maybe you have them mixed up in the schematics ?
Sure, I'll see if I can find a way of testing that, thanks
for testing the bus, the emmc sends a test pattern and the software must validate if the pattern was correctly received. If you mixed up some lines in hardware then bit 1 will arrive as bit 4, etc. so it will always fail
but it looks like bit 0 is correctly set ?
this is the test pattern in at91bootstrap
unsigned char data_8bits[8] = {0x55, 0xaa, 0, 0, 0, 0, 0, 0};
unsigned char data_4bits[4] = {0x5a, 0, 0, 0};
you can print the actual data that is received from the emmc there, and compare.. see how wrong it is.
I am still unsure if the switch function fails or there is an actual bus test error.
It seems to fail on mmc_bus_width_select
which is the command before the data is sent. the response code on that one is -10
fails, even when I force it to be MMC_BUS_WIDTH_1
Okay so we need to go back... the extended CSD is received correctly ? Try to print it out (mmc_card_identify). This extended CSD should be received through the DAT lines.. if I remember correctly
You can also try to comment the switch_fun call which moves to HIGH speed mode (EXT_CSD byte 185 ). Then proceed normal with the initialization. Some memories do not like the signals after moving to high speed mode.
here is extended CSD:
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0xca 0x1 0x0
0x3 0x0 0x0 0x0 0x0 0x0 0x5 0x0 0x1 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x5 0x0 0x2 0x0 0x7 0x0 0x2 0x1 0x0 0x0 0x0 0x0 0x0 0x8 0x8 0x8
0x8 0x8 0x8 0x0 0x0 0x0 0x0 0x0 0x0 0x10 0x0 0x8 0x8 0x0 0x1 0x1
0x0 0x5 0x8 0x0 0x7 0x3 0x2 0x15 0x6 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x7a 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0x0 0x0 0x0 0x1 0x3 0x1 0x0 0x0 0x0 0x0 0x0 0x0 0x0
Tried that, kept it in low speed mode, verified on oscilloscope, 400kHz clock speed
I was able to get Linux to recognise it and mount it if I set the Linux device tree to bus width 1, with a slower clock.
For now I'm happy that it's somewhat working and I'll take up further issues with the manufacturer. Thanks @ehristev for your help debugging, much appreciated! 🤺
Hi all,
I hope this is the right forum for this, if not please point me in the right direction.
We have a custom board, using a SAMA5D27 D1G CU, and a Micron MTFC2GMDEA-0M WT 2GB eMMC.
Schematic has been verified and board layout:
I can't get it to be recognised by u-boot, but at91 bootstrap does show some interesting data, however it returns an error (-10) when running
mmc_cmd_switch_fun()
on line 791 ofmci_media.c
CONFIG_DEBUG_VERY_LOUD
is set.The CID looks correct, and it detects the right version, but that's all I can get out of it. I've been banging my head off this for a week or so now so any help would be greatly appreciated.
Thanks