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

Siarhei Siamashka
2015-01-18T21:46:36Z

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 ;-)

To sum it up. We need motivated testers in order to improve things.
Clever hackers are not really required.

--
Best regards,
Siarhei Siamashka