Discussion:
[PATCH 0/5] Add 3GiB DRAM support to 64-bit Allwinner SoCs
(too old to reply)
Icenowy Zheng
2018-02-07 19:35:21 UTC
Permalink
Raw Message
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(-)
--
2.15.1
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-07 19:35:22 UTC
Permalink
Raw Message
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 <***@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
}, {
--
2.15.1
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
André Przywara
2018-02-08 00:34:29 UTC
Permalink
Raw Message
On 07/02/18 19:35, Icenowy Zheng wrote:

Hi,
Post by Icenowy Zheng
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 <***@arm.com>

Cheers,
Andre.
Post by Icenowy Zheng
---
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
}, {
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-07 19:35:23 UTC
Permalink
Raw Message
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 <***@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
--
2.15.1
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
André Przywara
2018-02-08 00:35:31 UTC
Permalink
Raw Message
Post by Icenowy Zheng
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.
Post by Icenowy Zheng
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.
Post by Icenowy Zheng
---
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Chen-Yu Tsai
2018-02-08 02:14:00 UTC
Permalink
Raw Message
Post by André Przywara
Post by Icenowy Zheng
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.
Post by Icenowy Zheng
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
Post by André Przywara
Thanks,
Andre.
Post by Icenowy Zheng
---
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.
For more options, visit https://groups.google.com/d/optout.
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-08 06:43:36 UTC
Permalink
Raw Message
在 2018-02-08 10:14,Chen-Yu Tsai 写道:
Post by Chen-Yu Tsai
Post by André Przywara
Post by Icenowy Zheng
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().
Post by Chen-Yu Tsai
Post by André Przywara
Post by Icenowy Zheng
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.)
Post by Chen-Yu Tsai
Post by André Przywara
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
Post by André Przywara
Thanks,
Andre.
Post by Icenowy Zheng
---
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
For more options, visit https://groups.google.com/d/optout.
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-07 19:35:24 UTC
Permalink
Raw Message
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 <***@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
--
2.15.1
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
André Przywara
2018-02-08 00:37:22 UTC
Permalink
Raw Message
On 07/02/18 19:35, Icenowy Zheng wrote:

Hi,
Post by Icenowy Zheng
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.
Post by Icenowy Zheng
---
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
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-08 07:03:51 UTC
Permalink
Raw Message
在 2018-02-08 08:37,André Przywara 写道:
Post by André Przywara
Hi,
Post by Icenowy Zheng
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.
- 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.
Post by André Przywara
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.
Post by André Przywara
Cheers,
Andre.
Post by Icenowy Zheng
---
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
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-08 08:10:54 UTC
Permalink
Raw Message
在 2018-02-08 08:37,André Przywara 写道:
Post by André Przywara
Hi,
Post by Icenowy Zheng
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.
- 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.
Post by André Przywara
- 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 ;-)
Post by André Przywara
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.
Post by Icenowy Zheng
---
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
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-07 19:35:25 UTC
Permalink
Raw Message
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 <***@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(&para);

/* 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, &para);
mctl_set_cr(socid, &para);

- 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);
}
--
2.15.1
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
André Przywara
2018-02-08 00:37:45 UTC
Permalink
Raw Message
On 07/02/18 19:35, Icenowy Zheng wrote:

Hi,
Post by Icenowy Zheng
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.
---
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.
Post by Icenowy Zheng
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(&para);
/* 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, &para);
mctl_set_cr(socid, &para);
- 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);
}
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-08 06:56:01 UTC
Permalink
Raw Message
在 2018-02-08 08:37,André Przywara 写道:
Post by André Przywara
Hi,
Post by Icenowy Zheng
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.
---
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.
Post by André Przywara
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.
Post by André Przywara
Cheers,
Andre.
Post by Icenowy Zheng
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(&para);
/* 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, &para);
mctl_set_cr(socid, &para);
- 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);
}
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Icenowy Zheng
2018-02-07 19:35:26 UTC
Permalink
Raw Message
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 <***@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();
--
2.15.1
--
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+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...