[U-Boot] [PATCH v4] mmc: socfpga_dw_mmc: Enable calibration for drvsel and smplsel

Chin Liang See clsee at altera.com
Wed Jan 27 14:13:40 CET 2016


On Wed, 2016-01-27 at 00:01 +0000, Trent Piepho wrote:
> On Fri, 2015-11-27 at 15:22 +0800, Chin Liang See wrote:
> > Enable SDMMC calibration to determine the best setting for
> > drvsel and smplsel. Calibration will be triggered if the
> > drvsel and smplsel node are not available in DTS.
> 
> We have a Cyclone V based board and on the latest revision the SD
> card
> interface has become unreliable at 50 MHz.  The SD card moved a few
> inches further away from the SoC in this revision.  I though maybe
> smplsel could be an issue and found this patch.
> 
> I ported this to our board, but found that this algorithm doesn't
> appear
> to work that well for us.
> 
> In my testing I found the fastest way to produce SD errors on Linux
> was
> to repeatedly issue two sector read multiple commands.  This produces
> about one error per 10,000 commands.  Usually a CRC error on the
> response but also data CRC errors and data stop bit errors.
> 
> This calibration code tests by using a single set block length
> command
> to check if the combination of drvsel and smplsel is good.  Obviously
> if
> 0.01% of commands fail then checking via the result of one command is
> nearly useless.  And indeed this is the case, every cal test passes
> and
> one gets a table of all trues.


Do note that these cal value are not passed to Linux. Wonder your Linux
is using the cal value as obtained from U-Boot calibration?

> 
> It is however worse than that.  Some cal settings are clearly bad. 
>  For
> instance, drvsel 3 smplsel 7 does not work at all on our board. 
>  Every
> read command tried with those settings will fail.  But the set block
> length command succeeds.  Perhaps because it neither sends nor
> receives
> any data?  


Per SD specifications, set block length (CMD16) will expect response R1
which is normal response from the card.


> So the calibration seems unlikely to improve anything, since
> it will always choose 3, 3 for the settings.  The basic premise, that
> it
> can tell if a pair of settings work or not, appears to not be true.


Wonder any difference if you change the value in DTS (without the
calibration code)? I am referring U-Boot accessing the SD card.


> 
> > +static int socfpga_dwmci_find_row_col_fit_rectangle(unsigned
> > rect_width,
> > +	unsigned rect_height,
> > +	unsigned char
> > cal_results[SOCFPGA_SD_DRVSEL][SOCFPGA_SD_SMPLSEL],
> > +	unsigned int *cal_row, unsigned int *cal_col)
> 
> There is no documentation of what exactly parameters are here.  But
> one
> can determine that cal_row will contain the zero based index of the
> "best" row.
> 


Oh there is a link at the function's comment to explain the algo.


> 
> > +	for (row = 0; row < SOCFPGA_SD_DRVSEL; row++) {
> > +		for (col = 0; col < SOCFPGA_SD_SMPLSEL; col++) {
> > +			priv->drvsel = row + 1;
> > +			priv->smplsel = col;
> 
> Here drvsel is set to row + 1.


This is also part of comment. In quick, we are seeing meta stability
issue when drvsel = 0 and that why we skip it


> 
> > +
> > +	err = socfpga_dwmci_find_calibration_point(cal_results,
> > sum,
> > +						   &priv->drvsel,
> > +						   &priv
> > ->smplsel);
> 
> But this function returns the zero based row number (I think it would
> be
> easier to notice if it were documented) in priv->drvsel.  Not row +
> 1.
> It seems that you will always program drvsel to be 1 smaller than it
> should be.

Same as previous comment

Thanks
Chin Liang


More information about the U-Boot mailing list