[U-Boot] Dynamically determine RAM size and pass it to kernel

We have some Zynq based boards still in the field that have only 512MB RAM instead of 1GB. The memory chips are compatible and use the same settings apart from that one extra address bit.
So what works is just configure the DDR controller for 1GB and then check if writing some data "wraps" back, this is my "spike" code in the RAM init code for that:
+ u32 *ptr_1 = (u32*)0x10000; + u32 *ptr_2 = (u32*)((gd->ram_size >> 1) + 0x10000); + + puts("RAM test"); + *ptr_1 = 0x12345678; + if (*ptr_2 == *ptr_1) { + *ptr_1 = 0x87654321; + if (*ptr_2 == *ptr_1) { + puts(" [HALF]"); + gd->ram_size >>= 1; + } + }
This works well, and reliably detects that the board only has half the amount of RAM, and corrects the ram_size variable.
The problem I'm seeing now is that this new ram_size does not get passed to the kernel. Apparently in modern versions of u-boot I need to somehow patch the "live" devicetree blob as well? How does that work?
Kind regards,
Mike Looijmans System Expert
TOPIC Products Materiaalweg 4, NL-5681 RJ Best Postbus 440, NL-5680 AK Best Telefoon: +31 (0) 499 33 69 79 E-mail: mike.looijmans@topicproducts.com Website: www.topicproducts.com
Please consider the environment before printing this e-mail

On 17-11-16 13:34, Mike Looijmans wrote:
We have some Zynq based boards still in the field that have only 512MB RAM instead of 1GB. The memory chips are compatible and use the same settings apart from that one extra address bit.
So what works is just configure the DDR controller for 1GB and then check if writing some data "wraps" back, this is my "spike" code in the RAM init code for that:
u32 *ptr_1 = (u32*)0x10000;
u32 *ptr_2 = (u32*)((gd->ram_size >> 1) + 0x10000);
puts("RAM test");
*ptr_1 = 0x12345678;
if (*ptr_2 == *ptr_1) {
*ptr_1 = 0x87654321;
if (*ptr_2 == *ptr_1) {
puts(" [HALF]");
gd->ram_size >>= 1;
}
}
I found that I can replace that with "get_mem_size()" which does this better.
This works well, and reliably detects that the board only has half the amount of RAM, and corrects the ram_size variable.
The problem I'm seeing now is that this new ram_size does not get passed to the kernel. Apparently in modern versions of u-boot I need to somehow patch the "live" devicetree blob as well? How does that work?
Kind regards,
Mike Looijmans System Expert
TOPIC Products Materiaalweg 4, NL-5681 RJ Best Postbus 440, NL-5680 AK Best Telefoon: +31 (0) 499 33 69 79 E-mail: mike.looijmans@topicproducts.com Website: www.topicproducts.com
Please consider the environment before printing this e-mail

On 17.11.2016 15:09, Mike Looijmans wrote:
On 17-11-16 13:34, Mike Looijmans wrote:
We have some Zynq based boards still in the field that have only 512MB RAM instead of 1GB. The memory chips are compatible and use the same settings apart from that one extra address bit.
So what works is just configure the DDR controller for 1GB and then check if writing some data "wraps" back, this is my "spike" code in the RAM init code for that:
u32 *ptr_1 = (u32*)0x10000;
u32 *ptr_2 = (u32*)((gd->ram_size >> 1) + 0x10000);
puts("RAM test");
*ptr_1 = 0x12345678;
if (*ptr_2 == *ptr_1) {
*ptr_1 = 0x87654321;
if (*ptr_2 == *ptr_1) {
puts(" [HALF]");
gd->ram_size >>= 1;
}
}
I found that I can replace that with "get_mem_size()" which does this better.
You have some ways. 1. Rewrite dram_init() function to run this test. 2. Let SPL find out and add two dtbs to it. IIRC board_fit_config_name_match() is that function which can decide that. 3. If you use module, look at spd eeprom and read it which is something what I was playing with on zcu102. Freescale boards in past used this a lot.
Thanks, Michal
participants (2)
-
Michal Simek
-
Mike Looijmans