[U-Boot] [PATCH 3/9] sunxi: Stop differentiating between 512M and 1G variants of the same board

Hans de Goede
2015-01-19T14:35:27Z

Hi,

On 18-01-15 22:46, Siarhei Siamashka wrote:
> On Sun, 18 Jan 2015 13:23:26 +0100
> Hans de Goede <hdegoede@redhat.com> wrote:
>
>> While working on adding more boards I noticed that we lack a config for
>> the 512M cubieboard, and that some of the new boards which I want to add also
>> have 512M and 1G variants, rather then adding 2 defconfig's for all of these,
>> lets switch the exising boards which have both a 512M and 1024M variant over
>> to the sun4i dram autoconfig code.
>>
>> This also drops the foo_RAMSIZE_defconfig variants of boards where we currently
>> have 2 separate configs already.
>>
>> Note:
>> 1) The newly introduced CONFIG_DRAM_EMR1 kconfig value is not used with
>> a value other then its default for now, but we need this to be configurable
>> to support some new boards with auto dram config.
>>
>> 2) We always set all CONFIG_DRAM_foo values in defconfigs, even if they match
>> the defaults, this is done to make it more clear what values are used for a
>> certain board.
>>
>> This has been tested on a Mele A1000, Mini-X and a Cubieboard, all 1G
>> variants, the dram autoconfig code has also been tested on a 512M mk802
>> (a defconfig for the mk802 is added in a later patch).
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>
> Thanks for finally finding time to do some refinements in this pile of
> junk dram settings for the boards that you are maintaining.
>
> I think that adding the Kconfig options is fine as long as they
> are not abused and the 'dram_para' structure is kept. We want to
> be able to update DRAM settings without the need of recompiling SPL.
> Currently this can be relatively easily done by finding and patching
> the 'dram_para' structure inside of the SPL binary.
>
> In general this looks like a good change. However see below.
>
> [...]
>
>> +++ b/board/sunxi/dram_sun4i_auto.c
>> @@ -0,0 +1,31 @@
>> +/* this file is generated, don't edit it yourself */
>> +
>> +#include <common.h>
>> +#include <asm/arch/dram.h>
>> +
>> +static struct dram_para dram_para = {
>> + .clock = CONFIG_DRAM_CLK,
>> + .type = 3,
>> + .rank_num = 1,
>> + .density = 0,
>> + .io_width = 0,
>> + .bus_width = 0,
>> + .cas = 6,
>> + .zq = CONFIG_DRAM_ZQ,
>> + .odt_en = 0,
>> + .size = 0,
>> + .tpr0 = 0x30926692,
>> + .tpr1 = 0x1090,
>> + .tpr2 = 0x1a0c8,
>> + .tpr3 = 0,
>> + .tpr4 = 0,
>> + .tpr5 = 0,
>> + .emr1 = CONFIG_DRAM_EMR1,
>> + .emr2 = 0,
>> + .emr3 = 0,
>> +};
>
> As we already discussed earlier
> http://lists.denx.de/pipermail/u-boot/2014-September/189266.html
> these tpr0/tpr1/tpr2 settings are configured for DDR2-800E (and 400MHz
> clock speed because of double data rate). Yes, DDR2 (!) instead of
> DDR3. This in practice is not very much off from DDR3-800, except for
> the tXS parameter. But tXS is only relevant for self-refresh, which is
> currently not used by the u-boot or the mainline kernel anyway. That's
> why this all does not crash and burn in an obvious way.
>
> Anyway, these timings are still wrong for the boards running DRAM
> at the clock speeds higher than 400MHz. For example, they are ~20%
> outside of the valid range at 480MHz and this all works by pure luck,
> thanks to the hardware typically having some safety/overclocking margin.
>
> If we look at the parameters used by the sun7i boards:
> .cas = 9,
> .tpr0 = 0x42d899b7,
> .tpr1 = 0xa090,
> .tpr2 = 0x22a00,
> ... then we can see that the settings are also a bit fishy. The
> tpr1/tpr2 parameters are matching DDR3-800 timings. And tpr0 is
> matching DDR3-1333 timings with 1KB (!) page size, while many sunxi
> devices are using 2KB pages. So it's some weird crossbreed, which
> is however somewhat less wrong than the settings from sun4i boards.
>
> I would suggest trying one of the following DRAM settings, generated
> as explained at http://linux-sunxi.org/Mainline_U-boot#DRAM_Settings
> And injecting the .clock, .zq and .emr1 parameters from Kconfig.
>
> static struct dram_para dram_para = { /* DRAM timings: 7-7-7-18 (480 MHz) */
> .clock = 480,
> .type = 3,
> .rank_num = 1,
> .cas = 7,
> .zq = 0x7b,
> .odt_en = 0,
> .tpr0 = 0x30927790,
> .tpr1 = 0xa0b0,
> .tpr2 = 0x23200,
> .tpr3 = 0x0,
> .tpr4 = 0x0,
> .tpr5 = 0x0,
> .emr1 = 0x0,
> .emr2 = 0x8,
> .emr3 = 0x0,
> .active_windowing = 1,
> };
>
> static struct dram_para dram_para = { /* DRAM timings: 7-8-8-20 (528 MHz) */
> .clock = 528,
> .type = 3,
> .rank_num = 1,
> .cas = 7,
> .zq = 0x7b,
> .odt_en = 0,
> .tpr0 = 0x36948890,
> .tpr1 = 0xa0c0,
> .tpr2 = 0x23600,
> .tpr3 = 0x0,
> .tpr4 = 0x0,
> .tpr5 = 0x0,
> .emr1 = 0x0,
> .emr2 = 0x8,
> .emr3 = 0x0,
> .active_windowing = 1,
> };
>
> Alternatively, we can add runtime calculation of cas/tpr0/tpr1/tpr2/emr2
> parameters directly into SPL, thus better matching the selected DRAM
> clock speed and reducing memory access latency. The disadvantages of
> this approach are:
> 1. Somewhat increased SPL size.
> 2. Some DDR3 chips have better timings than generic JEDEC speed bins, so
> using generic timings for every board may be not very optimal.
>
> This all is only blocked on the lack of cooperation from the u-boot
> sunxi boards maintainers, who appear to be kinda happy with the status
> quo and prefer the sacred magic settings from the vendors over what is
> suggested by the geeks doing reverse engineering ;-)

Siarhei, thanks for bringing this topic up once again, I agree that this
is ideally something which we should fix. The problem is that the only
way to know that any new settings which we do are actually good, is to
test them on lots of boards, and I do not mean one of each board, but
at least 10 of each board or some such.

Unfortunately that is not really feasible due to -ENOHWARDARE (not 10
of each) and -ENOTIME.

Still I would like to get this sorted, so I would like to move to the
recommended timings for the generic JEDEC speed bins, you rightfully
point out that those may not be 100% optimal, but given that we're
dealing with a lot of cheap boards, I think that those are our best bet.

The plan would be for you to submit a patch for that, and then I'll add
that to my sunxi-wip branch right away, this way all the testing I do,
as well as all the testing people using my sunxi-wip branch do will use
the new timings, and then once v2015.04 stabilizes a bit we can add
that patch to u-boot-sunxi/next, getting it ready for v2015.07 .

Does that sound like a plan ?

Ian, what do you think about this ?

As for runtime calculation, it might be easier to instead do something
like this in the "new" dram_sun4i_auto.c file which my patch-set
introduces:

#if CONFIG_DRAM_CLK > 528
#error DRAM clocks above 528 Mhz are not supported
#elif CONFIG_DRAM_CLK > 480

static struct dram_para dram_para = { /* DRAM timings: 7-8-8-20 (528 MHz) */
.clock = CONFIG_DRAM_CLK,
...
};

#elif CONFIG_DRAM_CLK > 400

static struct dram_para dram_para = { /* DRAM timings: 7-7-7-18 (480 MHz) */
.clock = CONFIG_DRAM_CLK,
...
};

#elif CONFIG_DRAM_CLK > 360

static struct dram_para dram_para = { /* DRAM timings: a-b-c-d (400 MHz) */
.clock = CONFIG_DRAM_CLK,
...
};

#else

static struct dram_para dram_para = { /* DRAM timings: a-b-c-d (360 MHz) */
.clock = CONFIG_DRAM_CLK,
...
};

#endif

This way we will not grow the spl, and keep an easy editable set of
dram_para in the spl for people who like to hexedit the spl ...

Regards,

Hans