imx8m+ usdhc delay line slave override problem

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

imx8m+ usdhc delay line slave override problem

300 Views
steveren
Contributor I

Slightly long question about using the USDHC controller in a bit of an unusual way, but it doesn't seem to be behaving entirely as it should.

We’re using – perhaps abusing – an eMMC interface to connect to custom FPGA logic rather than a plain memory device, and because we have some quite long PCB tracks, the delays can be significant even for relatively lower speeds. Specifically, we want to use DDR52 and calibrate the delay register at boot time for each processor instance. I’m trying to do this by finding an optimal tap value for the delay register and setting it directly in DLL slave override mode.

The algorithm is straightforward: for each delay tap in sequence, try to read both the Extended CSD register and a 512-byte data block, in case the different internal implementations behave differently. The expected behaviour is that there will be a consistent range of successful reads with a slightly variable transition to consistent failure and back again. I’m observing this on a test board in some cases but not the majority.

The following is a simplified version of code that demonstrates the inconsistency.

#define DLL_REG_OFFS  0x60
#define BASE_ADDR     0x30b60000 
#define DLL_REG       (BASE_ADDR+DLL_REG_OFFS)   

#define DLL_TAPS      128
#define DLL_OVERRIDE  0x100
#define DLL_TAPSEL_B  9
     
// assume these functions exist with the obvious meanings
void WriteRegister (uint32_t addr, uint32_t value);
int TestReadMMCExtCSD (void);
int TestReadMMCDataBlock (void);

for (int tap = 0; tap < DLL_TAPS; ++tap)
{
     uint32_t regval = DLL_OVERRIDE + (tap << DLL_TAPSEL_B);

     WriteRegister (DLL_REG, regval);

     int err1 = TestReadMMCExtCSD();
     int err2 = TestReadMMCDataBlock();
     int n = 0;
     if (err1)
           n += 1;
     if (err2)
           n += 2;

     printf ("%c", "+12-"[n]);
}

The output from a number of runs looks like this: ‘+’ signifies that both reads passed for a delay tap; ‘-‘ that both failed; and ‘1’ or ‘2’ if just the ECSD or data reads failed, respectively. The two runs that behaved exactly as expected are in green [remembering that the sequences can wrap as a long positive delay is equivalent to a short negative delay].

++++++++++++++++++++++++++++++++++------------++++++++++++++++++++++++++++++++++++++++-------------------------+++++++++++++++++
+++++1+++1++++++++++++++++++++++++------------------++++++++++++++---------------------------------------------+++++++++++++++++
+++++++++1+++++++++++++++++++++++++---------------------------------------------------------------------------2+++++++++++++++++
+++++++++++-++++++++++++++++++1+++----------------------------------------------------------------------------2+++++++++++++++++
++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------2+++++++++++++++++
+++++++++++++++++++++++++++++++++++-----------++++++++++++----------------------------------------------------1+++++++++++++++++
++++++++++++++++++++++++++++++++++2-----------------++++++++++++++++++++++++++++++++--------------------------2+++++++++++++++++
++++++++++++++++++++++++++++++++++1-----------++++++++++++++++----------------+++++++++++++++++++++++++++++---2+++++++++++++++++
+++++++++1++++++++++++++++++++++++----------------------------------------------------------------------------2+++++++++++++++++
++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------2+++++++++++++++++
+++++++++++++++++++++++++++++++++++---------++----------------------------------------------------------------2+++++++++++++++++
++++++++++++++++++++++++++++++++++----------++----------------------------------------------------------------2+++++++++++++++++
+++++++-++++++++++++++++++++++++++2-----------++++------------------------------------------------------------++++++++++++++++++
+++++++1++++++++++++++++++++++1+++----------++++++++++++------------------------------------------------------2+++++++++++++++++
++++++++++++++++++++++++++++++1+++----------------------------------------------------------------------------2+++++++++++++++++

An additional fact which may or may not be relevant is that when I get a read failure, that’s typically reflected in the INT_STATUS register with the DEBE and DCE bits as expected, but I also sometimes see bit 15 set, despite it being documented as reserved and always reading 0.

I’ve got a heuristic procedure – ignore and repeat runs with more than two groups of contiguous ‘+’ results (with wraps merged), then pick the middle of the larger range if more than one – that seems to give reliable results, but on a development board which doesn’t fully reflect the final product, that’s not entirely comfortable.

I’ve checked the published errata and nothing seems relevant, but this is not something that many people are likely to be trying to do, so it’s quite possible we’re the first to run into something previously unseen.

Any help or suggestions for further investigation gratefully received.

0 Kudos
Reply
0 Replies