Since my last post with my updated n800 kernel, I’ve spent some time looking at a troublesome MMC card – it’s a Transcend 4GB MMCplus card. It’s one of these technically out-of-spec byte-addressed 4GB cards, but in theory it should work just fine. I was alerted about the card by Frantisek Dufka who bought one and has had a lot of trouble with it in the n800, so I picked one up to take a look at what was going on. Now, unfortunately, I was unable to replicate Frantisek’s problem which remains unsolved, but I did see another problem – where the card would almost always freak out when switched into highspeed mode – yet the card worked just fine in highspeed mode in laptop’s SDHCI reader.
At around the same time I was looking at this, Pierre Ossman was doing some investigating of his own and concluded that it was not safe to assume that all controllers can handle the MMC and SD highspeed timings. These are close to the legacy timings, and to each other, but all three are slightly different. Accordingly, he made a change upstream to add explicit capability flags for highspeed support and to default that support to off. I took this patch and applied it to my n800 kernel, and then being the foolhardy guy I am, marked the omap reader as highspeed capable. I did this becaue I knew that my other highspeed cards work fine, but I did not expect it to make the Transcend card work – yet it did!
The only change that Pierre made that could cause this was that he updated the host controller with the current card flags after toggling the highspeed mode. I believe that this update, which is technically gratuitous as the controller state is already correct, introduces a delay that smooths over whatever was confusing the card originally. Now, I can consistently use the Transcend card.
An additional thing I investigated was why my dual-voltage MMCmobile cards were not running at 1.8V even though the omap controller claimed to support low voltage operations. When I looked into this, I saw that the MMC subsystem was interpreting the voltage flags incorrectly, apparently due to being based on an inaccurate spec that originated from Sandisk. This caused the code to interpret the actual low voltage support bit as a higher voltage and a set of reserved bits as indicating low voltage support. Once I fixed this, low voltage cards were able to run at 1.8V in the n800. This is nice because low voltage operations means lower power consumption and longer battery life. The only catch is that when I tried out the 64MB RS-MMC card that originally came with the Nokia 770, the card freaked out despite claiming to support low voltage operations; it would work fine at 2.0V or higher. Very strange.
Anyway, I’ve built a new kernel binary with all of these patches applied and it is available here. If you’re feeling cautious about my highspeed or low voltage patches, you can build your own kernel and exclude the patches you don’t want – but it would be great if you could try the full kernel out and report any problems you observe.
Update: So, I didn’t explain how to interpret the debug output, and that would probably be a good thing to do:
- clock: The clockspeed the card is being run at.
- MMC: 20Mhz
- SD: 25Mhz
- Highspeed MMC: 26Mhz or 52Mhz (clamped to 48MHz by the controller)
- Highspeed SD: 50Mhz (also clamped to 48MHz
- vdd: The selected voltage. There’s a long list but in practice, you’ll only see three values used.
- 16: 3.0V in the internal slot
- 15: 2.8V in the external slot
- 7: Low-voltage. 1.85V in the internal slot and 1.8V in the external slot
Yes, that means that the two slots actually run at different voltages. The external slot supports a wider range of voltages but as the lowest possible is always chosen, you won’t see them used.
- width: The width of the data bus
- 0: 1 bit
- 2: 4 bits
- timing: The timing mode. You can deduce this from the card type and the printed clockspeed, so this isn’t very profound.
- 0: Lowspeed (same for MMC and SD)
- 1: MMC highspeed
- 2: SD highspeed