Re: [U-Boot] [PATCH] overo: add SPL support

On Wednesday, December 14, 2011 06:24:13 PM Steve Sakoman wrote:
I think you will also need to update the get_board_revision function to ensure that SPL works with very early Overo revisions.
Note this excerpt from the X-loader get_board_revision funtion:
/* board revisions <= R2410 connect 4030 irq_1 to gpio112 */ /* these boards should return a revision number of 0 */ /* the code below forces a 4030 RTC irq to ensure that gpio112 is low */ #ifdef CONFIG_DRIVER_OMAP34XX_I2C i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); data = 0x01; i2c_write(0x4B, 0x29, 1, &data, 1); data = 0x0c; i2c_write(0x4B, 0x2b, 1, &data, 1); i2c_read(0x4B, 0x2a, 1, &data, 1); #endif
Yup, ugly, but this is the only way to detect revision properly on those boards.
I tried the following (as you can see I already commented out the i2c-read-write for test):
int get_board_revision(void) { #ifdef CONFIG_DRIVER_OMAP34XX_I2C i2c_set_bus_num(TWL4030_I2C_BUS); /*data = 0x01; i2c_write(0x4B, 0x29, 1, &data, 1); data = 0x0c; i2c_write(0x4B, 0x2b, 1, &data, 1); i2c_read(0x4B, 0x2a, 1, &data, 1);*/ #endif .... }
SPL Boot process hangs on i2c_set_bus_num ( tested by removing i2c_set_bus_num -
proper operation ) with console freeze:
| U-Boot SPL 2011.12-rc1-00004-g06e42c6-dirty (Dec 15 2011 - 14:03:34) | Texas Instruments Revision detection unimplemented
The call stack for get_board_revision() is for SPL
s_init() mem_init() do_sdrc_init(..) get_board_mem_timings(..) get_board_revision(..)
It seems that the call to i2c_set_bus_num comes too early. Before I dive into x- loader analysis: Has anybody an idea what goes wrong?
Andreas

On Thu, Dec 15, 2011 at 7:34 AM, Andreas Müller schnitzeltony@gmx.de wrote:
On Wednesday, December 14, 2011 06:24:13 PM Steve Sakoman wrote:
I think you will also need to update the get_board_revision function to ensure that SPL works with very early Overo revisions.
Note this excerpt from the X-loader get_board_revision funtion:
/* board revisions <= R2410 connect 4030 irq_1 to gpio112 */ /* these boards should return a revision number of 0 */ /* the code below forces a 4030 RTC irq to ensure that gpio112 is low */ #ifdef CONFIG_DRIVER_OMAP34XX_I2C i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); data = 0x01; i2c_write(0x4B, 0x29, 1, &data, 1); data = 0x0c; i2c_write(0x4B, 0x2b, 1, &data, 1); i2c_read(0x4B, 0x2a, 1, &data, 1); #endif
Yup, ugly, but this is the only way to detect revision properly on those boards.
I tried the following (as you can see I already commented out the i2c-read-write for test):
int get_board_revision(void) { #ifdef CONFIG_DRIVER_OMAP34XX_I2C i2c_set_bus_num(TWL4030_I2C_BUS); /*data = 0x01; i2c_write(0x4B, 0x29, 1, &data, 1); data = 0x0c; i2c_write(0x4B, 0x2b, 1, &data, 1); i2c_read(0x4B, 0x2a, 1, &data, 1);*/ #endif .... }
SPL Boot process hangs on i2c_set_bus_num ( tested by removing i2c_set_bus_num -
proper operation ) with console freeze:
| U-Boot SPL 2011.12-rc1-00004-g06e42c6-dirty (Dec 15 2011 - 14:03:34) | Texas Instruments Revision detection unimplemented
The call stack for get_board_revision() is for SPL
s_init() mem_init() do_sdrc_init(..) get_board_mem_timings(..) get_board_revision(..)
It seems that the call to i2c_set_bus_num comes too early. Before I dive into x- loader analysis: Has anybody an idea what goes wrong?
Without digging too hard into overo stuff, we've only called i2c_init() on the main bus and the x-load snippet is on the slave bus.

On Thu, Dec 15, 2011 at 7:34 AM, Andreas Müller schnitzeltony@gmx.de wrote:
I tried the following (as you can see I already commented out the i2c-read-
write
for test):
int get_board_revision(void) { #ifdef CONFIG_DRIVER_OMAP34XX_I2C i2c_set_bus_num(TWL4030_I2C_BUS); /*data = 0x01; i2c_write(0x4B, 0x29, 1, &data, 1); data = 0x0c; i2c_write(0x4B, 0x2b, 1, &data, 1); i2c_read(0x4B, 0x2a, 1, &data, 1);*/ #endif .... }
SPL Boot process hangs on i2c_set_bus_num ( tested by removing i2c_set_bus_num -> proper operation ) with console freeze:
| U-Boot SPL 2011.12-rc1-00004-g06e42c6-dirty (Dec 15 2011 - 14:03:34) | Texas Instruments Revision detection unimplemented
The call stack for get_board_revision() is for SPL
s_init() mem_init() do_sdrc_init(..) get_board_mem_timings(..) get_board_revision(..)
It seems that the call to i2c_set_bus_num comes too early.
Sorry for spamming but I face black magic:
I added debug messages in omap24xx_i2c.c / i2c_set_bus_num().
* Version 1:
int i2c_set_bus_num(unsigned int bus) { puts("i2c_set_bus_num called 1\n"); if ((bus < 0) || (bus >= I2C_BUS_MAX)) { printf("Bad bus: %d\n", bus); return -1; } printf("Bus: %d\n", bus);
#if I2C_BUS_MAX == 3 if (bus == 2) { puts("i2c_set_bus_num called 2\n"); i2c_base = (struct i2c *)I2C_BASE3; puts("i2c_set_bus_num called 3\n"); } else #endif if (bus == 1) { puts("i2c_set_bus_num called 4\n"); i2c_base = (struct i2c *)I2C_BASE2; puts("i2c_set_bus_num called 5\n"); } else { puts("i2c_set_bus_num called 6\n"); i2c_base = (struct i2c *)I2C_BASE1; puts("i2c_set_bus_num called 7\n"); }
puts("i2c_set_bus_num called 8\n"); --> current_bus = bus;
puts("i2c_set_bus_num called 9\n"); if (!bus_initialized[current_bus]) i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 0; }
leads to
i2c_set_bus_num called 1 Bus: 0 i2c_set_bus_num called 6 i2c_set_bus_num called 7 i2c_set_bus_num called 8
* Version 2:
int i2c_set_bus_num(unsigned int bus) { puts("i2c_set_bus_num called 1\n"); if ((bus < 0) || (bus >= I2C_BUS_MAX)) { printf("Bad bus: %d\n", bus); return -1; } printf("Bus: %d\n", bus); --> printf("CurrentBus: %d\n", current_bus); printf("AdrCurrentBus: %X\n", ¤t_bus);
#if I2C_BUS_MAX == 3 if (bus == 2) { puts("i2c_set_bus_num called 2\n"); i2c_base = (struct i2c *)I2C_BASE3; puts("i2c_set_bus_num called 3\n"); } else #endif if (bus == 1) { puts("i2c_set_bus_num called 4\n"); i2c_base = (struct i2c *)I2C_BASE2; puts("i2c_set_bus_num called 5\n"); } else { puts("i2c_set_bus_num called 6\n"); i2c_base = (struct i2c *)I2C_BASE1; puts("i2c_set_bus_num called 7\n"); }
puts("i2c_set_bus_num called 8\n"); current_bus = bus;
puts("i2c_set_bus_num called 9\n"); if (!bus_initialized[current_bus]) i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 0; }
leads to
i2c_set_bus_num called 1 Bus: 0
It seems that accessing 'current_bus' causes trouble. Has anybody an explanation for that? I don't think this is related to i2c or overo. For a better picture I attached memory mappings.
Since I do not have JTAG for debugging, I think x-loader is also nice :(
Regards
Andreas

On Thursday, December 15, 2011 10:12:59 PM Andreas Müller wrote:
On Thu, Dec 15, 2011 at 7:34 AM, Andreas Müller schnitzeltony@gmx.de wrote:
I tried the following (as you can see I already commented out the i2c-read-
write
for test):
int get_board_revision(void) { #ifdef CONFIG_DRIVER_OMAP34XX_I2C
i2c_set_bus_num(TWL4030_I2C_BUS); /*data = 0x01; i2c_write(0x4B, 0x29, 1, &data, 1); data = 0x0c; i2c_write(0x4B, 0x2b, 1, &data, 1); i2c_read(0x4B, 0x2a, 1, &data, 1);*/
#endif .... }
SPL Boot process hangs on i2c_set_bus_num ( tested by removing
i2c_set_bus_num -> proper operation ) with console freeze: | U-Boot SPL 2011.12-rc1-00004-g06e42c6-dirty (Dec 15 2011 - 14:03:34) | Texas Instruments Revision detection unimplemented
The call stack for get_board_revision() is for SPL
s_init() mem_init() do_sdrc_init(..) get_board_mem_timings(..) get_board_revision(..)
It seems that the call to i2c_set_bus_num comes too early.
Sorry for spamming but I face black magic:
I added debug messages in omap24xx_i2c.c / i2c_set_bus_num().
- Version 1:
int i2c_set_bus_num(unsigned int bus) { puts("i2c_set_bus_num called 1\n"); if ((bus < 0) || (bus >= I2C_BUS_MAX)) { printf("Bad bus: %d\n", bus); return -1; } printf("Bus: %d\n", bus);
#if I2C_BUS_MAX == 3 if (bus == 2) { puts("i2c_set_bus_num called 2\n"); i2c_base = (struct i2c *)I2C_BASE3; puts("i2c_set_bus_num called 3\n"); } else #endif if (bus == 1) { puts("i2c_set_bus_num called 4\n"); i2c_base = (struct i2c *)I2C_BASE2; puts("i2c_set_bus_num called 5\n"); } else { puts("i2c_set_bus_num called 6\n"); i2c_base = (struct i2c *)I2C_BASE1; puts("i2c_set_bus_num called 7\n"); }
puts("i2c_set_bus_num called 8\n"); --> current_bus = bus;
puts("i2c_set_bus_num called 9\n"); if (!bus_initialized[current_bus]) i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 0; }
leads to
i2c_set_bus_num called 1 Bus: 0 i2c_set_bus_num called 6 i2c_set_bus_num called 7 i2c_set_bus_num called 8
- Version 2:
int i2c_set_bus_num(unsigned int bus) { puts("i2c_set_bus_num called 1\n"); if ((bus < 0) || (bus >= I2C_BUS_MAX)) { printf("Bad bus: %d\n", bus); return -1; } printf("Bus: %d\n", bus); --> printf("CurrentBus: %d\n", current_bus); printf("AdrCurrentBus: %X\n", ¤t_bus);
#if I2C_BUS_MAX == 3 if (bus == 2) { puts("i2c_set_bus_num called 2\n"); i2c_base = (struct i2c *)I2C_BASE3; puts("i2c_set_bus_num called 3\n"); } else #endif if (bus == 1) { puts("i2c_set_bus_num called 4\n"); i2c_base = (struct i2c *)I2C_BASE2; puts("i2c_set_bus_num called 5\n"); } else { puts("i2c_set_bus_num called 6\n"); i2c_base = (struct i2c *)I2C_BASE1; puts("i2c_set_bus_num called 7\n"); }
puts("i2c_set_bus_num called 8\n"); current_bus = bus;
puts("i2c_set_bus_num called 9\n"); if (!bus_initialized[current_bus]) i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 0; }
leads to
i2c_set_bus_num called 1 Bus: 0
It seems that accessing 'current_bus' causes trouble. Has anybody an explanation for that? I don't think this is related to i2c or overo. For a better picture I attached memory mappings.
'objdump -dSt' shows (the memory mappings I attached were not really helpful - sorry next time I know):
4020ae14 l O .data 00000004 i2c_base 80000068 l O .bss 00000004 current_bus 8000006c l O .bss 0000000c bus_initialized
'i2c_base' is correctly located in SRAM but 'current_bus' and 'bus_initialized' are located in CS0 SDRAM which is at the time of call not yet initalized. This fits to the crash behaviour: Accessing 'i2c_base' does not cause trouble. How can I move 'current_bus' and 'bus_initialized' to SRAM?
Andreas

On Mon, Dec 19, 2011 at 6:03 PM, Andreas Müller schnitzeltony@gmx.de wrote:
On Thursday, December 15, 2011 10:12:59 PM Andreas Müller wrote:
On Thu, Dec 15, 2011 at 7:34 AM, Andreas Müller schnitzeltony@gmx.de wrote:
I tried the following (as you can see I already commented out the i2c-read-
write
for test):
int get_board_revision(void) { #ifdef CONFIG_DRIVER_OMAP34XX_I2C
i2c_set_bus_num(TWL4030_I2C_BUS); /*data = 0x01; i2c_write(0x4B, 0x29, 1, &data, 1); data = 0x0c; i2c_write(0x4B, 0x2b, 1, &data, 1); i2c_read(0x4B, 0x2a, 1, &data, 1);*/
#endif .... }
SPL Boot process hangs on i2c_set_bus_num ( tested by removing
i2c_set_bus_num -> proper operation ) with console freeze: | U-Boot SPL 2011.12-rc1-00004-g06e42c6-dirty (Dec 15 2011 - 14:03:34) | Texas Instruments Revision detection unimplemented
The call stack for get_board_revision() is for SPL
s_init() mem_init() do_sdrc_init(..) get_board_mem_timings(..) get_board_revision(..)
It seems that the call to i2c_set_bus_num comes too early.
Sorry for spamming but I face black magic:
I added debug messages in omap24xx_i2c.c / i2c_set_bus_num().
- Version 1:
int i2c_set_bus_num(unsigned int bus) { puts("i2c_set_bus_num called 1\n"); if ((bus < 0) || (bus >= I2C_BUS_MAX)) { printf("Bad bus: %d\n", bus); return -1; } printf("Bus: %d\n", bus);
#if I2C_BUS_MAX == 3 if (bus == 2) { puts("i2c_set_bus_num called 2\n"); i2c_base = (struct i2c *)I2C_BASE3; puts("i2c_set_bus_num called 3\n"); } else #endif if (bus == 1) { puts("i2c_set_bus_num called 4\n"); i2c_base = (struct i2c *)I2C_BASE2; puts("i2c_set_bus_num called 5\n"); } else { puts("i2c_set_bus_num called 6\n"); i2c_base = (struct i2c *)I2C_BASE1; puts("i2c_set_bus_num called 7\n"); }
puts("i2c_set_bus_num called 8\n"); --> current_bus = bus;
puts("i2c_set_bus_num called 9\n"); if (!bus_initialized[current_bus]) i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 0; }
leads to
i2c_set_bus_num called 1 Bus: 0 i2c_set_bus_num called 6 i2c_set_bus_num called 7 i2c_set_bus_num called 8
- Version 2:
int i2c_set_bus_num(unsigned int bus) { puts("i2c_set_bus_num called 1\n"); if ((bus < 0) || (bus >= I2C_BUS_MAX)) { printf("Bad bus: %d\n", bus); return -1; } printf("Bus: %d\n", bus); --> printf("CurrentBus: %d\n", current_bus); printf("AdrCurrentBus: %X\n", ¤t_bus);
#if I2C_BUS_MAX == 3 if (bus == 2) { puts("i2c_set_bus_num called 2\n"); i2c_base = (struct i2c *)I2C_BASE3; puts("i2c_set_bus_num called 3\n"); } else #endif if (bus == 1) { puts("i2c_set_bus_num called 4\n"); i2c_base = (struct i2c *)I2C_BASE2; puts("i2c_set_bus_num called 5\n"); } else { puts("i2c_set_bus_num called 6\n"); i2c_base = (struct i2c *)I2C_BASE1; puts("i2c_set_bus_num called 7\n"); }
puts("i2c_set_bus_num called 8\n"); current_bus = bus;
puts("i2c_set_bus_num called 9\n"); if (!bus_initialized[current_bus]) i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 0; }
leads to
i2c_set_bus_num called 1 Bus: 0
It seems that accessing 'current_bus' causes trouble. Has anybody an explanation for that? I don't think this is related to i2c or overo. For a better picture I attached memory mappings.
'objdump -dSt' shows (the memory mappings I attached were not really helpful - sorry next time I know):
4020ae14 l O .data 00000004 i2c_base 80000068 l O .bss 00000004 current_bus 8000006c l O .bss 0000000c bus_initialized
'i2c_base' is correctly located in SRAM but 'current_bus' and 'bus_initialized' are located in CS0 SDRAM which is at the time of call not yet initalized. This fits to the crash behaviour: Accessing 'i2c_base' does not cause trouble. How can I move 'current_bus' and 'bus_initialized' to SRAM?
Ah-ha! Good work. If you initialize them to a non-zero value, statically (and make sure the code doesn't assume they're 0 by default), this will change.

On Tuesday, December 20, 2011 02:08:18 AM Tom Rini wrote:
'objdump -dSt' shows (the memory mappings I attached were not really helpful - sorry next time I know):
4020ae14 l O .data 00000004 i2c_base 80000068 l O .bss 00000004 current_bus 8000006c l O .bss 0000000c bus_initialized
'i2c_base' is correctly located in SRAM but 'current_bus' and 'bus_initialized' are located in CS0 SDRAM which is at the time of call not yet initalized. This fits to the crash behaviour: Accessing 'i2c_base' does not cause trouble. How can I move 'current_bus' and 'bus_initialized' to SRAM?
Ah-ha! Good work. If you initialize them to a non-zero value, statically (and make sure the code doesn't assume they're 0 by default), this will change.
LOL: I tried already to set them to 0!

Dear Tom Rini,
In message CA+M6bX=bBFBaVm4aD2hVJfLXovtGjmKO9V40E+NyWtMtoaOV6A@mail.gmail.com you wrote:
'i2c_base' is correctly located in SRAM but 'current_bus' and 'bus_initialized' are located in CS0 SDRAM which is at the time of call not yet initalized. This fits to the crash behaviour: Accessing 'i2c_base' does not cause trouble. How can I move 'current_bus' and 'bus_initialized' to SRAM?
I guess you really, really must use i2c before relocation? If possible, this should be avoided in the first place.
Ah-ha! Good work. If you initialize them to a non-zero value, statically (and make sure the code doesn't assume they're 0 by default), this will change.
No, this is justy hiding the problem, and the next one who believes the value doesn't fit and changes it back to 0 runs into the issue again. Rather use an explicit
int foo __attribute__ ((section(".data"))) = 0;
so everybody sees the real intention.
Best regards,
Wolfgang Denk

On Mon, Dec 19, 2011 at 10:43 PM, Wolfgang Denk wd@denx.de wrote:
Dear Tom Rini,
In message CA+M6bX=bBFBaVm4aD2hVJfLXovtGjmKO9V40E+NyWtMtoaOV6A@mail.gmail.com you wrote:
'i2c_base' is correctly located in SRAM but 'current_bus' and 'bus_initialized' are located in CS0 SDRAM which is at the time of call not yet initalized. This fits to the crash behaviour: Accessing 'i2c_base' does not cause trouble. How can I move 'current_bus' and 'bus_initialized' to SRAM?
I guess you really, really must use i2c before relocation? If possible, this should be avoided in the first place.
Yes, board rev detection to know how to configure SDRAM.
Ah-ha! Good work. If you initialize them to a non-zero value, statically (and make sure the code doesn't assume they're 0 by default), this will change.
No, this is justy hiding the problem, and the next one who believes the value doesn't fit and changes it back to 0 runs into the issue again. Rather use an explicit
int foo __attribute__ ((section(".data"))) = 0;
so everybody sees the real intention.
And I'll hit up <linux/compiler.h> and see if there's a shortcut and put it on my TODO list to clean up the existing areas (there's a few, but commented at least) that have the same need, but set to non-zero values. Thanks!

Dear Tom Rini,
In message CA+M6bXn_ZBqA8rosE4L4O+4Eu+grAhWgCZ=u=2Nomb6WcyL6-w@mail.gmail.com you wrote:
I guess you really, really must use i2c before relocation? =A0If possible, this should be avoided in the first place.
Yes, board rev detection to know how to configure SDRAM.
I don't consider this a valid reason (reading the SPD EEPROM would be such a reason). In almost all other cases it should be suffucient to configure the maximum number of memory banks and the maximum size of the memory banks and then use get_ram_size() to determine the actual amount of memory and to correctly initialize the memory controller.
Note that I don't insist on any changes to existing code here. This is just a recommendation which you may (or may not) consider for any future ports / implementations.
Best regards,
Wolfgang Denk

On Tuesday, December 20, 2011 12:41:08 PM you wrote:
Dear Tom Rini,
In message <CA+M6bXn_ZBqA8rosE4L4O+4Eu+grAhWgCZ=u=2Nomb6WcyL6-
w@mail.gmail.com> you wrote:
I guess you really, really must use i2c before relocation? =A0If possible, this should be avoided in the first place.
Yes, board rev detection to know how to configure SDRAM.
I don't consider this a valid reason (reading the SPD EEPROM would be such a reason). In almost all other cases it should be suffucient to configure the maximum number of memory banks and the maximum size of the memory banks and then use get_ram_size() to determine the actual amount of memory and to correctly initialize the memory controller.
Note that I don't insist on any changes to existing code here. This is just a recommendation which you may (or may not) consider for any future ports / implementations.
Dear Wolfgang Denk,
I agree to your concerns but - as I understood Steve Sakoman - here the situation is slightly different: At elder overo boards TWL4030 RTC irq is connected to gpio112. Unfortunately this pin is also used for binary revision detection. Therefore we need to send 'shut-up' to TWL4030 via i2c to avoid reading wrong revision. In SPL this must be done *before* SDRAM (timing) is set up, because the type of SDRAM is revision dependent.
Hope this helps
Andreas

Dear Andreas,
In message 201112201253.46991.schnitzeltony@gmx.de you wrote:
I agree to your concerns but - as I understood Steve Sakoman - here the situation is slightly different:
I think you misunderstand.
At elder overo boards TWL4030 RTC irq is connected to gpio112. Unfortunately this pin is also used for binary revision detection. Therefore we need to send 'shut-up' to TWL4030 via i2c to avoid reading wrong revision. In SPL this must be done *before* SDRAM (timing) is set up, because the type of SDRAM is revision dependent.
My suggestion was to check if memory initialization can not rather be done _without_ reading (and without otherwise knowing) the board type or revision. Usually this is possible, and I always prefer such auto-adjusting solutions over hard-wired approaches that break down when any of the expected inout data is not correct or not available.
Best regards,
Wolfgang Denk

On Tuesday, December 20, 2011 01:06:07 PM you wrote:
Dear Andreas,
In message 201112201253.46991.schnitzeltony@gmx.de you wrote:
I agree to your concerns but - as I understood Steve Sakoman - here the
situation is slightly different:
I think you misunderstand.
Yes I think too :-)
At elder overo boards TWL4030 RTC irq is connected to gpio112. Unfortunately this pin is also used for binary revision detection. Therefore we need to send 'shut-up' to TWL4030 via i2c to avoid reading wrong revision. In SPL this must be done *before* SDRAM (timing) is set up, because the type of SDRAM is revision dependent.
My suggestion was to check if memory initialization can not rather be done _without_ reading (and without otherwise knowing) the board type or revision. Usually this is possible, and I always prefer such auto-adjusting solutions over hard-wired approaches that break down when any of the expected inout data is not correct or not available.
Dear Wolfgang,
I don't know if I want to jump also into these changes now - especially since I am quite new here.. But for my intererst - since it seems more error tolerant: How is SDRAM timing set up without exactly knowing what type is connected? Is there a good example implementation in u-boot(-spl)?
Best regards
Andreas

On Tuesday 20 December 2011 06:09 PM, Andreas Müller wrote:
On Tuesday, December 20, 2011 01:06:07 PM you wrote:
Dear Andreas,
In message201112201253.46991.schnitzeltony@gmx.de you wrote:
I agree to your concerns but - as I understood Steve Sakoman - here the
situation is slightly different:
I think you misunderstand.
Yes I think too :-)
At elder overo boards TWL4030 RTC irq is connected to gpio112. Unfortunately this pin is also used for binary revision detection. Therefore we need to send 'shut-up' to TWL4030 via i2c to avoid reading wrong revision. In SPL this must be done *before* SDRAM (timing) is set up, because the type of SDRAM is revision dependent.
My suggestion was to check if memory initialization can not rather be done _without_ reading (and without otherwise knowing) the board type or revision. Usually this is possible, and I always prefer such auto-adjusting solutions over hard-wired approaches that break down when any of the expected inout data is not correct or not available.
Dear Wolfgang,
I don't know if I want to jump also into these changes now - especially since I am quite new here.. But for my intererst - since it seems more error tolerant: How is SDRAM timing set up without exactly knowing what type is connected? Is there a good example implementation in u-boot(-spl)?
Here is an example for automatic configuration with LPDDR2 memories in OMAP4.
http://git.denx.de/?p=u-boot.git;a=blob;f=arch/arm/cpu/armv7/omap-common/emi...
Look at the function emif_get_device_details().
The automatic settings make use of timing values from JEDEC spec that is guaranteed to be safe for all devices, but not necessarily optimal(but for all LPDDR2 devices I have seen so far their timings are not different from the JEDEC defaults). In addition, we need to know density etc. which can be read from the LPDDR2 device itself.
Something similar may be possible for LPDDR (I presume you are using LPDDR), but will be somewhat complex, to say the least. Please note that we have compiled out the above code from OMAP4 SPL due to space constraints!
If something like 'int foo __attribute__ ((section(".data"))) = 0;' is solving your problem that may be the easier solution at the moment.
br, Aneesh

Dear Andreas,
In message 201112201339.39460.schnitzeltony@gmx.de you wrote:
I don't know if I want to jump also into these changes now - especially since I am quite new here.. But for my intererst - since it seems more error tolerant: How is SDRAM timing set up without exactly knowing what type is connected? Is there a good example implementation in u-boot(-spl)?
In most cases thare is not an arbitrary range of RAM types, but only a pretty small selection; even more often they differ only in size, not in timings. It depends on the set of possible configurations and capabilities of the meory controller how to proceed then. Typically you will start with very conservative settings, and from the sizes found you will know the correct configuration.
As for examples: probably not much in SPL, but a number of PPC board use this. See for example "board/tqc/tqm8xx/tqm8xx.c" which probes several banks of memory in 8, 9, and 10 column mode and then adjusts timing, even taking into account that the CPU and bus clock (and thus the refresh timings) are variable on some of these boards (you can set the CPU clock through the "cpuclk" environment variable).
Best regards,
Wolfgang Denk

Hi Andreas,
On 12/20/11 13:53, Andreas Müller wrote:
On Tuesday, December 20, 2011 12:41:08 PM you wrote:
Dear Tom Rini,
In message <CA+M6bXn_ZBqA8rosE4L4O+4Eu+grAhWgCZ=u=2Nomb6WcyL6-
w@mail.gmail.com> you wrote:
I guess you really, really must use i2c before relocation? =A0If possible, this should be avoided in the first place.
Yes, board rev detection to know how to configure SDRAM.
I don't consider this a valid reason (reading the SPD EEPROM would be such a reason). In almost all other cases it should be suffucient to configure the maximum number of memory banks and the maximum size of the memory banks and then use get_ram_size() to determine the actual amount of memory and to correctly initialize the memory controller.
Note that I don't insist on any changes to existing code here. This is just a recommendation which you may (or may not) consider for any future ports / implementations.
Dear Wolfgang Denk,
I agree to your concerns but - as I understood Steve Sakoman - here the situation is slightly different: At elder overo boards TWL4030 RTC irq is connected to gpio112. Unfortunately this pin is also used for binary revision detection. Therefore we need to send 'shut-up' to TWL4030 via i2c to avoid reading wrong revision. In SPL this must be done *before* SDRAM (timing) is set up, because the type of SDRAM is revision dependent.
What about forging some very not optimized default DRAM settings, that suit any assembled DRAM and then when you have I2C access, reconfigure it - is it possible?

On Tue, Dec 20, 2011 at 4:20 AM, Igor Grinberg grinberg@compulab.co.ilwrote:
What about forging some very not optimized default DRAM settings, that suit any assembled DRAM and then when you have I2C access, reconfigure it - is it possible?
The board ID is used to determine some fairly fundamental things like how the address bits are multiplexed, bank size, number of banks, and timing.
Perhaps it might be possible to determine some non-optimal settings that can work with the current set of POP memories used, and also a scheme to modify the above on the fly while executing from said ram, but then one would have to revisit this every time a new vendor/type of POP was used.
That seems a lot more complex than the current method.
I suppose we could just drop support for the old boards in u-boot. Those folks could continue to use the current x-load solution. Or perhaps someone will come up with a more clever idea!
Steve

On Tuesday, December 20, 2011 02:55:50 PM you wrote:
On Tue, Dec 20, 2011 at 4:20 AM, Igor Grinberg grinberg@compulab.co.ilwrote:
What about forging some very not optimized default DRAM settings, that suit any assembled DRAM and then when you have I2C access, reconfigure it - is it possible?
The board ID is used to determine some fairly fundamental things like how the address bits are multiplexed, bank size, number of banks, and timing.
Perhaps it might be possible to determine some non-optimal settings that can work with the current set of POP memories used, and also a scheme to modify the above on the fly while executing from said ram, but then one would have to revisit this every time a new vendor/type of POP was used.
That seems a lot more complex than the current method.
I suppose we could just drop support for the old boards in u-boot. Those folks could continue to use the current x-load solution.
I am afraid you are right. It seems that the current U-boot/OMAP/SPL environment it is not designed to have i2c in early state when SDRAM is set up. My experience: * After moving the i2c variables to SDRAM, i2c_set_bus_num (and thereby i2c_init) work but i2c_write hangs when calling udelay because timer is not yet running. * This can be worked around by calling timer_init() within s_init(). With this setup booting is possible but I get MMC timeout messages from u-boot although kernel is loaded properly. * I don't know if this is the reason for timeout but I think successful booting is just by accident because the register pointer to global data is not yet set (i2c and timer use global data). I tried to setup global data earlier but up to now without success. Even if successful I think the number of friends for such a deep change is limited... Not to be misunderstood: This is no criticism to anybody. The experince that a design does not fit for a (corner case) request I have had in several projects :)
Or perhaps someone will come up with a more clever idea!
My suggestion:
* Soon: Clean up the patch already sent as reviewed and leave i2c TWL4030 shut- up out. As fallback for old boards leave x-load in oe meta-gumstix (maybe just create a different machine configuration). * Later: Think about a 'more probing' approach as suggested in this thread (or a combination e.g if revision 1 detected, check size of SDRAM and with the result deciding if this is a revision 1/0).
Anyway: The informations regarding SDRAM I copied from x-load. Since this is a bit fishing in the dark: Are there documents from gumstix available, describing which memories were used (with which revision :) or are these secret IP?
Regards
Andreas
participants (6)
-
Andreas Müller
-
Aneesh V
-
Igor Grinberg
-
Steve Sakoman
-
Tom Rini
-
Wolfgang Denk