diff mbox series

[U-Boot,3/5] sunxi: add 3GiB DRAM detection support in main U-Boot

Message ID 20180207193526.48434-4-icenowy@aosc.io
State Changes Requested
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series Add 3GiB DRAM support to 64-bit Allwinner SoCs | expand

Commit Message

Icenowy Zheng Feb. 7, 2018, 7:35 p.m. UTC
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(-)

Comments

Andre Przywara Feb. 8, 2018, 12:37 a.m. UTC | #1
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
>
Icenowy Zheng Feb. 8, 2018, 7:03 a.m. UTC | #2
在 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
>>
Icenowy Zheng Feb. 8, 2018, 8:10 a.m. UTC | #3
在 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
>>
diff mbox series

Patch

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