[U-Boot] [PATCH 0/5] Add 3GiB DRAM support to 64-bit Allwinner SoCs

Allwinner 64-bit SoCs have allocated 3GiB space in the memory map for DRAM. If memory bigger than 3GiB is installed (as memory usually come as pow of 2 and they are not known to support 3GiB LPDDR3 modules, it means 4GiB memory is installed), the whole 3GiB space can be all used.
However, in many situations we still only defined 2GiB for the DRAM.
Add support for 3GiB DRAM. Tested on a customized Pine A64-LTS with 4GiB LPDDR3 memory installed.
Icenowy Zheng (5): sunxi: map DRAM part with 3G size sunxi: add Kconfig option for the maximum accessible DRAM sunxi: add 3GiB DRAM detection support in main U-Boot sunxi: let sunxi_dram_init return unsigned long long sunxi: restrict the ram_size to the accessible range in SPL
arch/arm/include/asm/arch-sunxi/dram.h | 2 +- arch/arm/mach-sunxi/Kconfig | 7 +++++++ arch/arm/mach-sunxi/board.c | 2 +- arch/arm/mach-sunxi/dram_sun6i.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a23.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a33.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a83t.c | 2 +- arch/arm/mach-sunxi/dram_sun9i.c | 4 ++-- arch/arm/mach-sunxi/dram_sunxi_dw.c | 4 ++-- board/sunxi/board.c | 36 ++++++++++++++++++++++++++++++++-- board/sunxi/dram_sun4i_auto.c | 2 +- board/sunxi/dram_sun5i_auto.c | 2 +- include/configs/sunxi-common.h | 2 +- 13 files changed, 54 insertions(+), 15 deletions(-)

All Allwinner 64-bit SoCs now are known to be able to access 3GiB of external DRAM, however the size of DRAM part in the MMU translation table is still 2GiB.
Change the size of DRAM part in MMU table to 3GiB.
Signed-off-by: Icenowy Zheng icenowy@aosc.io --- arch/arm/mach-sunxi/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 0c60ee04da..4ee1040ac9 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -53,7 +53,7 @@ static struct mm_region sunxi_mem_map[] = { /* RAM */ .virt = 0x40000000UL, .phys = 0x40000000UL, - .size = 0x80000000UL, + .size = 0xC0000000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE }, {

On 07/02/18 19:35, Icenowy Zheng wrote:
Hi,
All Allwinner 64-bit SoCs now are known to be able to access 3GiB of external DRAM, however the size of DRAM part in the MMU translation table is still 2GiB.
Change the size of DRAM part in MMU table to 3GiB.
This is needed for the (new) get_ram_size() to work, isn't it?
I don't like this routine very much, but I guess this change here is fine anyway:
Reviewed-by: Andre Przywara andre.przywara@arm.com
Cheers, Andre.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
arch/arm/mach-sunxi/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index 0c60ee04da..4ee1040ac9 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -53,7 +53,7 @@ static struct mm_region sunxi_mem_map[] = { /* RAM */ .virt = 0x40000000UL, .phys = 0x40000000UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE }, {.size = 0xC0000000UL,

Allwinner 64-bit SoCs can use 4GiB DRAM chip, however their memory map has only allocated 3GiB for DRAM, so only 3GiB of the DRAM is accessible.
Add a Kconfig option for the maximum accessible DRAM.
For A80 it should be a much higher value (8GiB), but as I have no A80 device to test and originally U-Boot only supports 2GiB DRAM on A80, it currently still falls under the 2GiB situation.
Signed-off-by: Icenowy Zheng icenowy@aosc.io --- arch/arm/mach-sunxi/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 1fededd0a3..32739e0f33 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -63,6 +63,13 @@ config MACH_SUNXI_H3_H5 select SUNXI_GEN_SUN6I select SUPPORT_SPL
+# TODO: try out A80's 8GiB DRAM space +config SUNXI_DRAM_MAX_SIZE + hex + default 0xC0000000 if MACH_SUN50I + default 0xC0000000 if MACH_SUN50I_H5 + default 0x80000000 + choice prompt "Sunxi SoC Variant" optional

On 07/02/18 19:35, Icenowy Zheng wrote:
Allwinner 64-bit SoCs can use 4GiB DRAM chip, however their memory map has only allocated 3GiB for DRAM, so only 3GiB of the DRAM is accessible.
Add a Kconfig option for the maximum accessible DRAM.
That looks fine to me, but have you checked CONFIG_MAX_MEM_MAPPED? get_effective_memsize() in common/memsize.c looks like it's solving this very problem.
For A80 it should be a much higher value (8GiB), but as I have no A80 device to test and originally U-Boot only supports 2GiB DRAM on A80, it currently still falls under the 2GiB situation.
Well, that depends on how we will use SUNXI_DRAM_SIZE. If that's to limit the size we eventually report in the DT, that should be indeed 8GB on the A80. But U-Boot itself can't use more than 3GB on sunxi/ARMv7 (due to the static 1:1 mapping). I think we should separate those two numbers (actual DRAM size and U-Boot's own DRAM size), if we really want to support >3GB on the A80.
But maybe we should not get carried away by something that doesn't really exist.
Thanks, Andre.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
arch/arm/mach-sunxi/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 1fededd0a3..32739e0f33 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -63,6 +63,13 @@ config MACH_SUNXI_H3_H5 select SUNXI_GEN_SUN6I select SUPPORT_SPL
+# TODO: try out A80's 8GiB DRAM space +config SUNXI_DRAM_MAX_SIZE
- hex
- default 0xC0000000 if MACH_SUN50I
- default 0xC0000000 if MACH_SUN50I_H5
- default 0x80000000
choice prompt "Sunxi SoC Variant" optional

On Thu, Feb 8, 2018 at 8:35 AM, André Przywara andre.przywara@arm.com wrote:
On 07/02/18 19:35, Icenowy Zheng wrote:
Allwinner 64-bit SoCs can use 4GiB DRAM chip, however their memory map has only allocated 3GiB for DRAM, so only 3GiB of the DRAM is accessible.
Add a Kconfig option for the maximum accessible DRAM.
That looks fine to me, but have you checked CONFIG_MAX_MEM_MAPPED? get_effective_memsize() in common/memsize.c looks like it's solving this very problem.
For A80 it should be a much higher value (8GiB), but as I have no A80 device to test and originally U-Boot only supports 2GiB DRAM on A80, it currently still falls under the 2GiB situation.
Well, that depends on how we will use SUNXI_DRAM_SIZE. If that's to limit the size we eventually report in the DT, that should be indeed 8GB on the A80. But U-Boot itself can't use more than 3GB on sunxi/ARMv7 (due to the static 1:1 mapping). I think we should separate those two numbers (actual DRAM size and U-Boot's own DRAM size), if we really want to support >3GB on the A80.
But maybe we should not get carried away by something that doesn't really exist.
That was the first thing that popped up in my mind after seeing this series. A80 supports LPAE. However, the A80 is out of production, and no one produced any boards with more than 2GB of RAM. So >3GB on sunxi is going to go untested for a long time, if not forever.
ChenYu
Thanks, Andre.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
arch/arm/mach-sunxi/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 1fededd0a3..32739e0f33 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -63,6 +63,13 @@ config MACH_SUNXI_H3_H5 select SUNXI_GEN_SUN6I select SUPPORT_SPL
+# TODO: try out A80's 8GiB DRAM space +config SUNXI_DRAM_MAX_SIZE
hex
default 0xC0000000 if MACH_SUN50I
default 0xC0000000 if MACH_SUN50I_H5
default 0x80000000
choice prompt "Sunxi SoC Variant" optional
-- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.

在 2018-02-08 10:14,Chen-Yu Tsai 写道:
On Thu, Feb 8, 2018 at 8:35 AM, André Przywara andre.przywara@arm.com wrote:
On 07/02/18 19:35, Icenowy Zheng wrote:
Allwinner 64-bit SoCs can use 4GiB DRAM chip, however their memory map has only allocated 3GiB for DRAM, so only 3GiB of the DRAM is accessible.
Add a Kconfig option for the maximum accessible DRAM.
That looks fine to me, but have you checked CONFIG_MAX_MEM_MAPPED? get_effective_memsize() in common/memsize.c looks like it's solving this very problem.
get_effective_memsize() restricts memory size from gd->ram_size. gd->ram_size is defined as phys_size_t, which should be 32-bit on Allwinner SoCs except A80. (Although currently CONFIG_ARM64 selects CONFIG_PHYS_64BIT which makes phys_size_t 64-bit, the high 32-bit doesn't physically exist on those SoCs, and it's possible for a 32-bit SoC with 3GiB DRAM space to appear).
A 32-bit data type cannot store a size of 4GiB. This is the first reason that I doesn't rely on get_effective_memsize().
For A80 it should be a much higher value (8GiB), but as I have no A80 device to test and originally U-Boot only supports 2GiB DRAM on A80, it currently still falls under the 2GiB situation.
Well, that depends on how we will use SUNXI_DRAM_SIZE. If that's to limit the size we eventually report in the DT, that should be indeed 8GB on the A80. But U-Boot itself can't use more than 3GB on sunxi/ARMv7 (due to the static 1:1 mapping). I think we should separate those two numbers (actual DRAM size and U-Boot's own DRAM size), if we really want to support >3GB on the A80.
Yes, and the CONFIG_MAX_MEM_MAPPED should be used in A80 case, and the CONFIG_PHYS_64BIT option should be selected, as the internal bus of A80 is bigger than 4GiB.
So that the meaning of CONFIG_MAX_MEM_MAPPED is "maximum memory mapped in U-Boot", in A80 case only 3.5G is mapped in U-Boot, but Linux can use the other 4.5G.
(In this case another U-Boot stage code that doesn't scan DRAM size but calculate it from memory controller is needed.)
In A64/H5/H6 case the whole 3G accessible memory is mapped to U-Boot, and there's no memory that U-Boot cannot access but some other software can. So the gd->ram_size should be restricted at 3GiB. (The 1GiB is installed to the system, but it's not part of the system memory due to it's totally not accessible.)
But maybe we should not get carried away by something that doesn't really exist.
That was the first thing that popped up in my mind after seeing this series. A80 supports LPAE. However, the A80 is out of production, and no one produced any boards with more than 2GB of RAM. So >3GB on sunxi is going to go untested for a long time, if not forever.
ChenYu
Thanks, Andre.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
arch/arm/mach-sunxi/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 1fededd0a3..32739e0f33 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -63,6 +63,13 @@ config MACH_SUNXI_H3_H5 select SUNXI_GEN_SUN6I select SUPPORT_SPL
+# TODO: try out A80's 8GiB DRAM space +config SUNXI_DRAM_MAX_SIZE
hex
default 0xC0000000 if MACH_SUN50I
default 0xC0000000 if MACH_SUN50I_H5
default 0x80000000
choice prompt "Sunxi SoC Variant" optional
-- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.

Some Allwinner SoCs can use 3GiB DRAM (part of 4GiB or larger module).
As the common get_ram_size function cannot detect non-pow-of-2 memory, add special detect code into the DRAM size code in main U-Boot.
Signed-off-by: Icenowy Zheng icenowy@aosc.io --- board/sunxi/board.c | 23 +++++++++++++++++++++++ include/configs/sunxi-common.h | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8891961dcc..8d707cbac2 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -256,7 +256,30 @@ int board_init(void)
int dram_init(void) { +#if PHYS_SDRAM_0_SIZE == (SZ_2G + SZ_1G) + /* + * get_ram_size() doesn't support non-pow-of-2 sizes, so the detection + * of 3GiB DRAM is implemented here. + * It just checks whether the DRAM is bigger than 2GiB, as the DRAM + * module is usually 4GiB in this case (and 1GiB is not accessible). + */ + u32 save_0, save_2g; + gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, SZ_2G); + if (gd->ram_size == SZ_2G) { + save_0 = readl(PHYS_SDRAM_0); + save_2g = readl(PHYS_SDRAM_0 + SZ_2G); + writel(0, PHYS_SDRAM_0); + writel(0xaa55aa55, PHYS_SDRAM_0 + SZ_2G); + dsb(); + if (readl(PHYS_SDRAM_0) != readl(PHYS_SDRAM_0 + SZ_2G)) { + gd->ram_size = SZ_2G + SZ_1G; + writel(save_2g, PHYS_SDRAM_0 + SZ_2G); + } + writel(save_0, PHYS_SDRAM_0); + } +#else gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE); +#endif
return 0; } diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 9b3944ad13..177647e009 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -111,7 +111,7 @@
#define CONFIG_NR_DRAM_BANKS 1 #define PHYS_SDRAM_0 CONFIG_SYS_SDRAM_BASE -#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GiB */ +#define PHYS_SDRAM_0_SIZE CONFIG_SUNXI_DRAM_MAX_SIZE
#ifdef CONFIG_AHCI #define CONFIG_SCSI_AHCI_PLAT

On 07/02/18 19:35, Icenowy Zheng wrote:
Hi,
Some Allwinner SoCs can use 3GiB DRAM (part of 4GiB or larger module).
As the common get_ram_size function cannot detect non-pow-of-2 memory, add special detect code into the DRAM size code in main U-Boot.
The original get_ram_size() function is slightly dodgy already (as it probes memory by writing). And in general we will never be able to cover ARMv7/LPAE machines easily with our current static identify mapping - regardless of any probing hacks we pull up.
So I was wondering if we could either: - somehow pass the result of sunxi_dram_init() to U-Boot proper, or - call the DRAM size determination routine again
This would give us the definite answer, and would be correct in every case. We just need to limit it to the memory map limit, if any.
But his function below looks really like a hack. If at all, it should be part of the get_ram_size() routine itself, as this is not sunxi specific.
Cheers, Andre.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
board/sunxi/board.c | 23 +++++++++++++++++++++++ include/configs/sunxi-common.h | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8891961dcc..8d707cbac2 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -256,7 +256,30 @@ int board_init(void)
int dram_init(void) { +#if PHYS_SDRAM_0_SIZE == (SZ_2G + SZ_1G)
- /*
* get_ram_size() doesn't support non-pow-of-2 sizes, so the detection
* of 3GiB DRAM is implemented here.
* It just checks whether the DRAM is bigger than 2GiB, as the DRAM
* module is usually 4GiB in this case (and 1GiB is not accessible).
*/
- u32 save_0, save_2g;
- gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, SZ_2G);
- if (gd->ram_size == SZ_2G) {
save_0 = readl(PHYS_SDRAM_0);
save_2g = readl(PHYS_SDRAM_0 + SZ_2G);
writel(0, PHYS_SDRAM_0);
writel(0xaa55aa55, PHYS_SDRAM_0 + SZ_2G);
dsb();
if (readl(PHYS_SDRAM_0) != readl(PHYS_SDRAM_0 + SZ_2G)) {
gd->ram_size = SZ_2G + SZ_1G;
writel(save_2g, PHYS_SDRAM_0 + SZ_2G);
}
writel(save_0, PHYS_SDRAM_0);
- }
+#else gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE); +#endif
return 0; } diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 9b3944ad13..177647e009 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -111,7 +111,7 @@
#define CONFIG_NR_DRAM_BANKS 1 #define PHYS_SDRAM_0 CONFIG_SYS_SDRAM_BASE -#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GiB */ +#define PHYS_SDRAM_0_SIZE CONFIG_SUNXI_DRAM_MAX_SIZE
#ifdef CONFIG_AHCI #define CONFIG_SCSI_AHCI_PLAT

在 2018-02-08 08:37,André Przywara 写道:
On 07/02/18 19:35, Icenowy Zheng wrote:
Hi,
Some Allwinner SoCs can use 3GiB DRAM (part of 4GiB or larger module).
As the common get_ram_size function cannot detect non-pow-of-2 memory, add special detect code into the DRAM size code in main U-Boot.
The original get_ram_size() function is slightly dodgy already (as it probes memory by writing). And in general we will never be able to cover ARMv7/LPAE machines easily with our current static identify mapping - regardless of any probing hacks we pull up.
So I was wondering if we could either:
- somehow pass the result of sunxi_dram_init() to U-Boot proper, or
- call the DRAM size determination routine again
This would give us the definite answer, and would be correct in every case. We just need to limit it to the memory map limit, if any.
Okay. Let me try.
But his function below looks really like a hack. If at all, it should be part of the get_ram_size() routine itself, as this is not sunxi specific.
This hack is too immature to be a common hack, it just consider 4GiB as 3GiB, so it's still a sunxi specific hack.
Cheers, Andre.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
board/sunxi/board.c | 23 +++++++++++++++++++++++ include/configs/sunxi-common.h | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8891961dcc..8d707cbac2 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -256,7 +256,30 @@ int board_init(void)
int dram_init(void) { +#if PHYS_SDRAM_0_SIZE == (SZ_2G + SZ_1G)
- /*
* get_ram_size() doesn't support non-pow-of-2 sizes, so the
detection
* of 3GiB DRAM is implemented here.
* It just checks whether the DRAM is bigger than 2GiB, as the DRAM
* module is usually 4GiB in this case (and 1GiB is not accessible).
*/
- u32 save_0, save_2g;
- gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, SZ_2G);
- if (gd->ram_size == SZ_2G) {
save_0 = readl(PHYS_SDRAM_0);
save_2g = readl(PHYS_SDRAM_0 + SZ_2G);
writel(0, PHYS_SDRAM_0);
writel(0xaa55aa55, PHYS_SDRAM_0 + SZ_2G);
dsb();
if (readl(PHYS_SDRAM_0) != readl(PHYS_SDRAM_0 + SZ_2G)) {
gd->ram_size = SZ_2G + SZ_1G;
writel(save_2g, PHYS_SDRAM_0 + SZ_2G);
}
writel(save_0, PHYS_SDRAM_0);
- }
+#else gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE); +#endif
return 0; } diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 9b3944ad13..177647e009 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -111,7 +111,7 @@
#define CONFIG_NR_DRAM_BANKS 1 #define PHYS_SDRAM_0 CONFIG_SYS_SDRAM_BASE -#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GiB */ +#define PHYS_SDRAM_0_SIZE CONFIG_SUNXI_DRAM_MAX_SIZE
#ifdef CONFIG_AHCI #define CONFIG_SCSI_AHCI_PLAT

在 2018-02-08 08:37,André Przywara 写道:
On 07/02/18 19:35, Icenowy Zheng wrote:
Hi,
Some Allwinner SoCs can use 3GiB DRAM (part of 4GiB or larger module).
As the common get_ram_size function cannot detect non-pow-of-2 memory, add special detect code into the DRAM size code in main U-Boot.
The original get_ram_size() function is slightly dodgy already (as it probes memory by writing). And in general we will never be able to cover ARMv7/LPAE machines easily with our current static identify mapping - regardless of any probing hacks we pull up.
So I was wondering if we could either:
- somehow pass the result of sunxi_dram_init() to U-Boot proper, or
Where to pass it?
I don't think currently we pass anything from SPL to U-Boot. And it's still a bit possible to use BSP boot0 with mainline U-Boot.
- call the DRAM size determination routine again
I checked the DRAM controller of H6, and it's not easy to re-calc the DRAM size -- the DRAM size is only considered when constructing ADDRMAP registers. We may need to emulate part of the DRAM controller to calc the size ;-)
This would give us the definite answer, and would be correct in every case. We just need to limit it to the memory map limit, if any.
But his function below looks really like a hack. If at all, it should be part of the get_ram_size() routine itself, as this is not sunxi specific.
Cheers, Andre.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
board/sunxi/board.c | 23 +++++++++++++++++++++++ include/configs/sunxi-common.h | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8891961dcc..8d707cbac2 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -256,7 +256,30 @@ int board_init(void)
int dram_init(void) { +#if PHYS_SDRAM_0_SIZE == (SZ_2G + SZ_1G)
- /*
* get_ram_size() doesn't support non-pow-of-2 sizes, so the
detection
* of 3GiB DRAM is implemented here.
* It just checks whether the DRAM is bigger than 2GiB, as the DRAM
* module is usually 4GiB in this case (and 1GiB is not accessible).
*/
- u32 save_0, save_2g;
- gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, SZ_2G);
- if (gd->ram_size == SZ_2G) {
save_0 = readl(PHYS_SDRAM_0);
save_2g = readl(PHYS_SDRAM_0 + SZ_2G);
writel(0, PHYS_SDRAM_0);
writel(0xaa55aa55, PHYS_SDRAM_0 + SZ_2G);
dsb();
if (readl(PHYS_SDRAM_0) != readl(PHYS_SDRAM_0 + SZ_2G)) {
gd->ram_size = SZ_2G + SZ_1G;
writel(save_2g, PHYS_SDRAM_0 + SZ_2G);
}
writel(save_0, PHYS_SDRAM_0);
- }
+#else gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE); +#endif
return 0; } diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 9b3944ad13..177647e009 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -111,7 +111,7 @@
#define CONFIG_NR_DRAM_BANKS 1 #define PHYS_SDRAM_0 CONFIG_SYS_SDRAM_BASE -#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GiB */ +#define PHYS_SDRAM_0_SIZE CONFIG_SUNXI_DRAM_MAX_SIZE
#ifdef CONFIG_AHCI #define CONFIG_SCSI_AHCI_PLAT

As 4GiB capacity is above the range of 32-bit unsigned integer, raise the return type of sunxi_dram_init() to unsigned long long, thus it can hold 4GiB capacity (or maybe more on A80).
Some controllers that are possible to use 4GiB+ memory module are also changed to calculate its memory capacity in unsigned long long.
Signed-off-by: Icenowy Zheng icenowy@aosc.io --- arch/arm/include/asm/arch-sunxi/dram.h | 2 +- arch/arm/mach-sunxi/dram_sun6i.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a23.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a33.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a83t.c | 2 +- arch/arm/mach-sunxi/dram_sun9i.c | 4 ++-- arch/arm/mach-sunxi/dram_sunxi_dw.c | 4 ++-- board/sunxi/board.c | 2 +- board/sunxi/dram_sun4i_auto.c | 2 +- board/sunxi/dram_sun5i_auto.c | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h index 80abac95b8..d08b82371d 100644 --- a/arch/arm/include/asm/arch-sunxi/dram.h +++ b/arch/arm/include/asm/arch-sunxi/dram.h @@ -32,7 +32,7 @@ #include <asm/arch/dram_sun4i.h> #endif
-unsigned long sunxi_dram_init(void); +unsigned long long sunxi_dram_init(void); void mctl_await_completion(u32 *reg, u32 mask, u32 val); bool mctl_mem_matches(u32 offset);
diff --git a/arch/arm/mach-sunxi/dram_sun6i.c b/arch/arm/mach-sunxi/dram_sun6i.c index 5dbbf6186f..bdf52a2c38 100644 --- a/arch/arm/mach-sunxi/dram_sun6i.c +++ b/arch/arm/mach-sunxi/dram_sun6i.c @@ -326,7 +326,7 @@ static void mctl_port_cfg(void) writel(0x00000307, &mctl_com->mbagcr[5]); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a23.c b/arch/arm/mach-sunxi/dram_sun8i_a23.c index c53671a0e9..169ccff41a 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a23.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a23.c @@ -264,7 +264,7 @@ static void mctl_init(u32 *bus_width) writel(0x00000000, &mctl_ctl->rfshctl3); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c index fa1620cb39..dfbbe6f39c 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a33.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c @@ -325,7 +325,7 @@ static void mctl_sys_init(struct dram_para *para) udelay(250); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a83t.c b/arch/arm/mach-sunxi/dram_sun8i_a83t.c index 55df1b9d54..ec4bccd635 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a83t.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a83t.c @@ -423,7 +423,7 @@ static void mctl_sys_init(struct dram_para *para) udelay(250); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun9i.c b/arch/arm/mach-sunxi/dram_sun9i.c index 8c681f3541..dcb20f763e 100644 --- a/arch/arm/mach-sunxi/dram_sun9i.c +++ b/arch/arm/mach-sunxi/dram_sun9i.c @@ -854,7 +854,7 @@ signed int DRAMC_get_dram_size(void) return 1 << dram_size; }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -957,5 +957,5 @@ unsigned long sunxi_dram_init(void) mctl_com_init(¶);
/* return the proper RAM size */ - return DRAMC_get_dram_size() << 20; + return ((unsigned long long)DRAMC_get_dram_size()) << 20; } diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c index 78b4ffb9c3..3bff1c46cd 100644 --- a/arch/arm/mach-sunxi/dram_sunxi_dw.c +++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c @@ -682,7 +682,7 @@ static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para) 3, 3, 3, 3, 3, 3, 3, 3, \ 3, 3, 3, 3, 2, 0, 0 }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -763,6 +763,6 @@ unsigned long sunxi_dram_init(void) mctl_auto_detect_dram_size(socid, ¶); mctl_set_cr(socid, ¶);
- return (1UL << (para.row_bits + para.bank_bits)) * para.page_size * + return (1ULL << (para.row_bits + para.bank_bits)) * para.page_size * (para.dual_rank ? 2 : 1); } diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8d707cbac2..5828d47294 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -601,7 +601,7 @@ void sunxi_board_init(void) #endif #endif printf("DRAM:"); - gd->ram_size = sunxi_dram_init(); + gd->ram_size = (phys_size_t)sunxi_dram_init(); printf(" %d MiB\n", (int)(gd->ram_size >> 20)); if (!gd->ram_size) hang(); diff --git a/board/sunxi/dram_sun4i_auto.c b/board/sunxi/dram_sun4i_auto.c index 7d4409b51e..293c968f6b 100644 --- a/board/sunxi/dram_sun4i_auto.c +++ b/board/sunxi/dram_sun4i_auto.c @@ -29,7 +29,7 @@ static struct dram_para dram_para = { .dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY, };
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { return dramc_init(&dram_para); } diff --git a/board/sunxi/dram_sun5i_auto.c b/board/sunxi/dram_sun5i_auto.c index e3fa243267..02e29b215f 100644 --- a/board/sunxi/dram_sun5i_auto.c +++ b/board/sunxi/dram_sun5i_auto.c @@ -32,7 +32,7 @@ static struct dram_para dram_para = { .dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY, };
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { return dramc_init(&dram_para); }

On 07/02/18 19:35, Icenowy Zheng wrote:
Hi,
As 4GiB capacity is above the range of 32-bit unsigned integer, raise the return type of sunxi_dram_init() to unsigned long long, thus it can hold 4GiB capacity (or maybe more on A80). Some controllers that are possible to use 4GiB+ memory module are also changed to calculate its memory capacity in unsigned long long.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
arch/arm/include/asm/arch-sunxi/dram.h | 2 +- arch/arm/mach-sunxi/dram_sun6i.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a23.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a33.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a83t.c | 2 +- arch/arm/mach-sunxi/dram_sun9i.c | 4 ++-- arch/arm/mach-sunxi/dram_sunxi_dw.c | 4 ++-- board/sunxi/board.c | 2 +- board/sunxi/dram_sun4i_auto.c | 2 +- board/sunxi/dram_sun5i_auto.c | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h index 80abac95b8..d08b82371d 100644 --- a/arch/arm/include/asm/arch-sunxi/dram.h +++ b/arch/arm/include/asm/arch-sunxi/dram.h @@ -32,7 +32,7 @@ #include <asm/arch/dram_sun4i.h> #endif
-unsigned long sunxi_dram_init(void); +unsigned long long sunxi_dram_init(void);
Since this is explicitly about > 4GB/32 bits, I would suggest we just use uint64_t here, instead of guessing what long long means.
But can't we just change the semantics of sunxi_dram_init() to return megabytes instead? sun9i already uses this internally, and just blows it up in the wrapper. I don't think we have anything with a granularity smaller than 1MB? Then we could just leave it at native bit size, and spare poor ARMv7 from struggling with 64 bit arithmetic.
Cheers, Andre.
void mctl_await_completion(u32 *reg, u32 mask, u32 val); bool mctl_mem_matches(u32 offset);
diff --git a/arch/arm/mach-sunxi/dram_sun6i.c b/arch/arm/mach-sunxi/dram_sun6i.c index 5dbbf6186f..bdf52a2c38 100644 --- a/arch/arm/mach-sunxi/dram_sun6i.c +++ b/arch/arm/mach-sunxi/dram_sun6i.c @@ -326,7 +326,7 @@ static void mctl_port_cfg(void) writel(0x00000307, &mctl_com->mbagcr[5]); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a23.c b/arch/arm/mach-sunxi/dram_sun8i_a23.c index c53671a0e9..169ccff41a 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a23.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a23.c @@ -264,7 +264,7 @@ static void mctl_init(u32 *bus_width) writel(0x00000000, &mctl_ctl->rfshctl3); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c index fa1620cb39..dfbbe6f39c 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a33.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c @@ -325,7 +325,7 @@ static void mctl_sys_init(struct dram_para *para) udelay(250); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a83t.c b/arch/arm/mach-sunxi/dram_sun8i_a83t.c index 55df1b9d54..ec4bccd635 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a83t.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a83t.c @@ -423,7 +423,7 @@ static void mctl_sys_init(struct dram_para *para) udelay(250); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun9i.c b/arch/arm/mach-sunxi/dram_sun9i.c index 8c681f3541..dcb20f763e 100644 --- a/arch/arm/mach-sunxi/dram_sun9i.c +++ b/arch/arm/mach-sunxi/dram_sun9i.c @@ -854,7 +854,7 @@ signed int DRAMC_get_dram_size(void) return 1 << dram_size; }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -957,5 +957,5 @@ unsigned long sunxi_dram_init(void) mctl_com_init(¶);
/* return the proper RAM size */
- return DRAMC_get_dram_size() << 20;
- return ((unsigned long long)DRAMC_get_dram_size()) << 20;
} diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c index 78b4ffb9c3..3bff1c46cd 100644 --- a/arch/arm/mach-sunxi/dram_sunxi_dw.c +++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c @@ -682,7 +682,7 @@ static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para) 3, 3, 3, 3, 3, 3, 3, 3, \ 3, 3, 3, 3, 2, 0, 0 }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -763,6 +763,6 @@ unsigned long sunxi_dram_init(void) mctl_auto_detect_dram_size(socid, ¶); mctl_set_cr(socid, ¶);
- return (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
- return (1ULL << (para.row_bits + para.bank_bits)) * para.page_size * (para.dual_rank ? 2 : 1);
} diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8d707cbac2..5828d47294 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -601,7 +601,7 @@ void sunxi_board_init(void) #endif #endif printf("DRAM:");
- gd->ram_size = sunxi_dram_init();
- gd->ram_size = (phys_size_t)sunxi_dram_init(); printf(" %d MiB\n", (int)(gd->ram_size >> 20)); if (!gd->ram_size) hang();
diff --git a/board/sunxi/dram_sun4i_auto.c b/board/sunxi/dram_sun4i_auto.c index 7d4409b51e..293c968f6b 100644 --- a/board/sunxi/dram_sun4i_auto.c +++ b/board/sunxi/dram_sun4i_auto.c @@ -29,7 +29,7 @@ static struct dram_para dram_para = { .dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY, };
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { return dramc_init(&dram_para); } diff --git a/board/sunxi/dram_sun5i_auto.c b/board/sunxi/dram_sun5i_auto.c index e3fa243267..02e29b215f 100644 --- a/board/sunxi/dram_sun5i_auto.c +++ b/board/sunxi/dram_sun5i_auto.c @@ -32,7 +32,7 @@ static struct dram_para dram_para = { .dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY, };
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { return dramc_init(&dram_para); }

在 2018-02-08 08:37,André Przywara 写道:
On 07/02/18 19:35, Icenowy Zheng wrote:
Hi,
As 4GiB capacity is above the range of 32-bit unsigned integer, raise the return type of sunxi_dram_init() to unsigned long long, thus it can hold 4GiB capacity (or maybe more on A80). Some controllers that are possible to use 4GiB+ memory module are also changed to calculate its memory capacity in unsigned long long.
Signed-off-by: Icenowy Zheng icenowy@aosc.io
arch/arm/include/asm/arch-sunxi/dram.h | 2 +- arch/arm/mach-sunxi/dram_sun6i.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a23.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a33.c | 2 +- arch/arm/mach-sunxi/dram_sun8i_a83t.c | 2 +- arch/arm/mach-sunxi/dram_sun9i.c | 4 ++-- arch/arm/mach-sunxi/dram_sunxi_dw.c | 4 ++-- board/sunxi/board.c | 2 +- board/sunxi/dram_sun4i_auto.c | 2 +- board/sunxi/dram_sun5i_auto.c | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h index 80abac95b8..d08b82371d 100644 --- a/arch/arm/include/asm/arch-sunxi/dram.h +++ b/arch/arm/include/asm/arch-sunxi/dram.h @@ -32,7 +32,7 @@ #include <asm/arch/dram_sun4i.h> #endif
-unsigned long sunxi_dram_init(void); +unsigned long long sunxi_dram_init(void);
Since this is explicitly about > 4GB/32 bits, I would suggest we just use uint64_t here, instead of guessing what long long means.
Seems OK. But is there any sure suffix for uint64_t? For unsigned long long we can use ULL.
But can't we just change the semantics of sunxi_dram_init() to return megabytes instead? sun9i already uses this internally, and just blows it up in the wrapper. I don't think we have anything with a granularity smaller than 1MB? Then we could just leave it at native bit size, and spare poor ARMv7 from struggling with 64 bit arithmetic.
The calculated size is just in byte.
The A80 code first shifted it to MiB in DRAMC_get_dram_size() and then shifted it back to B in sunxi_dram_init(); however the code that shifts it to MiB only applies to drivers which have shift operation.
The other target driver, dram_sunxi_dw, uses both bit shifts and multiply when calculating the size, and to have 4096MiB value we still need to calculate the byte value as uint64_t and then shift it to MiB value. (The multiply value can get as high as 4096, so it's highly possible that the shift value could be less than 20.)
I think keeping the return value as byte will make the code more clear.
Cheers, Andre.
void mctl_await_completion(u32 *reg, u32 mask, u32 val); bool mctl_mem_matches(u32 offset);
diff --git a/arch/arm/mach-sunxi/dram_sun6i.c b/arch/arm/mach-sunxi/dram_sun6i.c index 5dbbf6186f..bdf52a2c38 100644 --- a/arch/arm/mach-sunxi/dram_sun6i.c +++ b/arch/arm/mach-sunxi/dram_sun6i.c @@ -326,7 +326,7 @@ static void mctl_port_cfg(void) writel(0x00000307, &mctl_com->mbagcr[5]); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a23.c b/arch/arm/mach-sunxi/dram_sun8i_a23.c index c53671a0e9..169ccff41a 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a23.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a23.c @@ -264,7 +264,7 @@ static void mctl_init(u32 *bus_width) writel(0x00000000, &mctl_ctl->rfshctl3); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c index fa1620cb39..dfbbe6f39c 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a33.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c @@ -325,7 +325,7 @@ static void mctl_sys_init(struct dram_para *para) udelay(250); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun8i_a83t.c b/arch/arm/mach-sunxi/dram_sun8i_a83t.c index 55df1b9d54..ec4bccd635 100644 --- a/arch/arm/mach-sunxi/dram_sun8i_a83t.c +++ b/arch/arm/mach-sunxi/dram_sun8i_a83t.c @@ -423,7 +423,7 @@ static void mctl_sys_init(struct dram_para *para) udelay(250); }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; diff --git a/arch/arm/mach-sunxi/dram_sun9i.c b/arch/arm/mach-sunxi/dram_sun9i.c index 8c681f3541..dcb20f763e 100644 --- a/arch/arm/mach-sunxi/dram_sun9i.c +++ b/arch/arm/mach-sunxi/dram_sun9i.c @@ -854,7 +854,7 @@ signed int DRAMC_get_dram_size(void) return 1 << dram_size; }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -957,5 +957,5 @@ unsigned long sunxi_dram_init(void) mctl_com_init(¶);
/* return the proper RAM size */
- return DRAMC_get_dram_size() << 20;
- return ((unsigned long long)DRAMC_get_dram_size()) << 20;
} diff --git a/arch/arm/mach-sunxi/dram_sunxi_dw.c b/arch/arm/mach-sunxi/dram_sunxi_dw.c index 78b4ffb9c3..3bff1c46cd 100644 --- a/arch/arm/mach-sunxi/dram_sunxi_dw.c +++ b/arch/arm/mach-sunxi/dram_sunxi_dw.c @@ -682,7 +682,7 @@ static void mctl_auto_detect_dram_size(uint16_t socid, struct dram_para *para) 3, 3, 3, 3, 3, 3, 3, 3, \ 3, 3, 3, 3, 2, 0, 0 }
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { struct sunxi_mctl_com_reg * const mctl_com = (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE; @@ -763,6 +763,6 @@ unsigned long sunxi_dram_init(void) mctl_auto_detect_dram_size(socid, ¶); mctl_set_cr(socid, ¶);
- return (1UL << (para.row_bits + para.bank_bits)) * para.page_size *
- return (1ULL << (para.row_bits + para.bank_bits)) * para.page_size * (para.dual_rank ? 2 : 1);
} diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 8d707cbac2..5828d47294 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -601,7 +601,7 @@ void sunxi_board_init(void) #endif #endif printf("DRAM:");
- gd->ram_size = sunxi_dram_init();
- gd->ram_size = (phys_size_t)sunxi_dram_init(); printf(" %d MiB\n", (int)(gd->ram_size >> 20)); if (!gd->ram_size) hang();
diff --git a/board/sunxi/dram_sun4i_auto.c b/board/sunxi/dram_sun4i_auto.c index 7d4409b51e..293c968f6b 100644 --- a/board/sunxi/dram_sun4i_auto.c +++ b/board/sunxi/dram_sun4i_auto.c @@ -29,7 +29,7 @@ static struct dram_para dram_para = { .dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY, };
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { return dramc_init(&dram_para); } diff --git a/board/sunxi/dram_sun5i_auto.c b/board/sunxi/dram_sun5i_auto.c index e3fa243267..02e29b215f 100644 --- a/board/sunxi/dram_sun5i_auto.c +++ b/board/sunxi/dram_sun5i_auto.c @@ -32,7 +32,7 @@ static struct dram_para dram_para = { .dqs_gating_delay = CONFIG_DRAM_DQS_GATING_DELAY, };
-unsigned long sunxi_dram_init(void) +unsigned long long sunxi_dram_init(void) { return dramc_init(&dram_para); }

On newer Allwinner SoCs with the BROM start at 0x0 and the DRAM space at <0x40000000 0xc0000000>, some parts of DRAM will be inaccessible when 4GiB module is used.
Restrict the ram_size written to global_data in SPL.
Signed-off-by: Icenowy Zheng icenowy@aosc.io --- board/sunxi/board.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 5828d47294..a6620f260a 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -541,6 +541,7 @@ int board_mmc_init(bd_t *bis) void sunxi_board_init(void) { int power_failed = 0; + unsigned long long dram_real_size;
#ifdef CONFIG_SY8106A_POWER power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT); @@ -601,8 +602,16 @@ void sunxi_board_init(void) #endif #endif printf("DRAM:"); - gd->ram_size = (phys_size_t)sunxi_dram_init(); - printf(" %d MiB\n", (int)(gd->ram_size >> 20)); + dram_real_size = sunxi_dram_init(); + printf(" %d MiB", (int)(dram_real_size >> 20)); + if (dram_real_size > CONFIG_SUNXI_DRAM_MAX_SIZE) { + gd->ram_size = CONFIG_SUNXI_DRAM_MAX_SIZE; + printf(", %d MiB usable\n", (int)(gd->ram_size >> 20)); + } else { + gd->ram_size = (phys_size_t) dram_real_size; + printf("\n"); + } + if (!gd->ram_size) hang();
participants (3)
-
André Przywara
-
Chen-Yu Tsai
-
Icenowy Zheng