Update s3c24x0 timer implementation
PATCH 1/1 Update s3c24x0 timer implementation
I have been doing some work to get U-Boot running on a samsung S3C2440 based SBC (QQ2440). I experienced several issues getting the board running including "raise: Signal # 8 caught" errors being printed to the console. After a bit of debugging with a JTAG debugger I found the problems were due to arch/arm/cpu/arm920t/s3c24x0/timer.c using several global variables prior to relocation to RAM. I noticed that the global variable .bss section is shared with the .rel.text section.
Since the .rel.text section is required by the relocation code, I
assume that .bss global variables cannot be used until after relocation?
After studying several other timer.c files I developed the following patch which uses the global data struct to store the global variables.
I also restructured some of the code based on structure of the othertimer.c files. I have confirmed it works correctly on the SBC I have.
Regards
Mark Norman
The s3c24x0 timer has been updated to use the global_data struct. Restructured code based on other timer.c files.
Updated comments and several parameters.
--- arch/arm/cpu/arm920t/s3c24x0/timer.c | 158 +++++++++++++-------------------- arch/arm/include/asm/global_data.h | 12 +-- 2 files changed, 66 insertions(+), 104 deletions(-)
(quoted diff) +0 -0
b/arch/arm/cpu/arm920t/s3c24x0/timer.c
index 9571870..1552345 100644
arch/arm/cpu/arm920t/s3c24x0/timer.c +62 -96
208 lines not on this page · raw message
(quoted diff) +0 -0
b/arch/arm/include/asm/global_data.h
index fac98d5..a20a9f7 100644
arch/arm/include/asm/global_data.h +4 -8
@@ -38,9 +38,6 @@ typedef struct global_data {unsigned long flags;unsigned long baudrate;unsigned long have_console;/* serial_init() was called */ -#ifdef CONFIG_PRE_CONSOLE_BUFFER -unsigned long precon_buf_idx;/* Pre-Console buffer index */ -#endif unsigned long env_addr;/* Address of Environment struct */ unsigned long env_valid;/* Checksum of Environment valid? */ unsigned long fb_base;/* base address of frame buffer */
@@ -67,6 +64,10 @@ typedef struct global_data {#ifdef CONFIG_IXP425 unsigned long timestamp;#endif +#ifdef CONFIG_S3C24X0 +unsigned long lastdec; +unsigned long timestamp; +#endif unsigned long relocaddr;/* Start address of U-Boot in RAM */ phys_size_t ram_size;/* RAM size */ unsigned long mon_len;/* monitor len */
@@ -78,11 +79,6 @@ typedef struct global_data {#endif void **jt;/* jump table */ char env_buf[32 ];/* buffer for getenv() before reloc. */ -#if defined(CONFIG_POST ) || defined(CONFIG_LOGBUFFER ) -unsigned long post_log_word;/* Record POST activities */ -unsigned long post_log_res;/* success of POST test */ -unsigned long post_init_f_time;/* When post_init_f started */ -#endif } gd_t;/*
Signature · 1 line
1.7.1
PATCH 1/1 Update s3c24x0 timer implementation
Dear Mark Norman,
Quoted 4 lines · In message <CAJtrzLOvjswmuww+xNLXxeSH4QxOBZww3JrZGKCgLq5w6B=y3w@mail.gmail.com>…
Since the .rel.text section is required by the relocation code, I
assume that .bss global variables cannot be used until after relocation?
Why do you have to make such assumptions? That's documented behaviour. Didn't you RTFM?
Quoted 4 lines
After studying several other
timer.cfiles I developed the following patch which uses the global data struct to store the global variables.
I also restructured some of the code based on structure of the othertimer.cfiles. I have confirmed it works correctly on the SBC I have.
Then please submit a proper patch - these introductury comments don;lt belong intot he commit message and shouldbemoved into the comment section (below the "---" line).
...
arch/arm/cpu/arm920t/s3c24x0/timer.c line 56
Quoted 5 lines
arch/arm/cpu/arm920t/s3c24x0/timer.c +5
-0+/* Use PWM Timer 4 because it has no output. +* Prescaler is hard fixed at 250, divider at 2. +* This generates a Timer clock frequency of 100kHz (@PCLK=50MHz) and +* therefore 10us timer ticks. +*/
Incorrect multiline comment format; please fix globally.
arch/arm/cpu/arm920t/s3c24x0/timer.c line 60
Quoted 3 lines
arch/arm/cpu/arm920t/s3c24x0/timer.c +3
-0+/* Prescaler for Timer 4 is 250 */ +const ulong prescaler =250 ; +writel ((prescaler-1 ) <<8 , &timers->tcfg0);
Please move declarations up. Don't split declarations by comment lines. Add a blank line between declarations and code.
...
arch/arm/include/asm/global_data.h typedef struct global_data { · line 43
Quoted 9 lines
arch/arm/include/asm/global_data.h +0
-3@@ -38,9 +38,6 @@ typedef struct global_data {unsigned long flags;unsigned long baudrate;unsigned long have_console;/* serial_init() was called */ -#ifdef CONFIG_PRE_CONSOLE_BUFFER -unsigned long precon_buf_idx;/* Pre-Console buffer index */ -#endif
Make sure not to add such unrelated, incorrect changes!
arch/arm/include/asm/global_data.h typedef struct global_data { · line 85
Quoted 5 lines
arch/arm/include/asm/global_data.h +0
-5-#if defined(CONFIG_POST ) || defined(CONFIG_LOGBUFFER ) -unsigned long post_log_word;/* Record POST activities */ -unsigned long post_log_res;/* success of POST test */ -unsigned long post_init_f_time;/* When post_init_f started */ -#endif
Ditto.
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I think there's a world market for about five computers.
-- attr. Thomas J. Watson (Chairman of the Board, IBM), 1943PATCH 1/1 Update s3c24x0 timer implementation
Dear Wolfgang Denk,
Thank you for your response.
Quoted 7 lines
Quoted 3 lines
?Since the .rel.text section is required by the relocation code, I assume that .bss global variables cannot be used until after relocation?
Why do you have to make such assumptions? ?That's documented behaviour. ?Didn't you RTFM?
I thought I had done a thorough search previously but after receiving your response I managed to find some of the details outlined in the README file.
I have attached an updated patch below which hopefully addresses the other issues you highlighted.
Kind Regards,
Mark Norman
The s3c24x0 timer has been updated to use the global_data struct. Restructured code based on other timer.c files.
Updated comments and several parameters.
--- arch/arm/cpu/arm920t/s3c24x0/timer.c | 155 +++++++++++++-------------------- arch/arm/include/asm/global_data.h | 4 + 2 files changed, 65 insertions(+), 94 deletions(-)
(quoted diff) +0 -0
b/arch/arm/cpu/arm920t/s3c24x0/timer.c
index 9571870..5695c62 100644
arch/arm/cpu/arm920t/s3c24x0/timer.c +61 -94
203 lines not on this page · raw message
(quoted diff) +0 -0
b/arch/arm/include/asm/global_data.h
index fac98d5..b836915 100644
arch/arm/include/asm/global_data.h +4 -0
@@ -67,6 +67,10 @@ typedef struct global_data {#ifdef CONFIG_IXP425 unsigned long timestamp;#endif +#ifdef CONFIG_S3C24X0 +unsigned long lastdec; +unsigned long timestamp; +#endif unsigned long relocaddr;/* Start address of U-Boot in RAM */ phys_size_t ram_size;/* RAM size */ unsigned long mon_len;/* monitor len */
Signature · 1 line
1.7.1
PATCH 1/1 Update s3c24x0 timer implementation
Quoted 11 lines
Dear Wolfgang Denk,
Thank you for your response.
Quoted 6 lines
Quoted 3 lines
Since the .rel.text section is required by the relocation code, I
assume that .bss global variables cannot be used until after relocation?Why do you have to make such assumptions? That's documented behaviour. Didn't you RTFM?
Quoted 6 lines
I thought I had done a thorough search previously but after receiving your response I managed to find some of the details outlined in the README file.
I have attached an updated patch below which hopefully addresses the other issues you highlighted.
Hehe, you should RTFM ;-) http://www.denx.de/wiki/U-Boot/Patches
Generally, use git send-email to send the patch.
Quoted 64 lines
Kind Regards,
Mark Norman
The s3c24x0 timer has been updated to use the
global_datastruct. Restructured code based on othertimer.cfiles.
Updated comments and several parameters.Signed-off-by Mark Norman <[email protected]>--- arch/arm/cpu/arm920t/s3c24x0/timer.c | 155 +++++++++++++-------------------- arch/arm/include/asm/global_data.h | 4 + 2 files changed, 65 insertions(+), 94 deletions(-)arch/arm/cpu/arm920t/s3c24x0/timer.c +10
-15@@ -35,142 +35,109 @@#include <asm/io.h> #include <asm/arch/s3c24x0_cpu.h> -int timer_load_val =0 ; -static ulong timer_clk; +DECLARE_GLOBAL_DATA_PTR ; -/* macro to read the 16 bit timer */ -static inline ulong READ_TIMER (void ) +/* Read the 16 bit timer */ +static inline ulong read_timer (void ) {struct s3c24x0_timers *timers =s3c24x0_get_base_timers ();return readl (&timers->tcnto4) &0xffff ; } -static ulong timestamp; -static ulong lastdec; -int timer_init (void ) { +/* +* PWM Timer 4 is used because it has no output. +* Prescaler is hard fixed at 250, divider at 2. +* This generates a Timer clock frequency of 100kHz (@PCLK=50MHz) and +* therefore 10us timer ticks. +*/ +const ulong prescaler =250 ;struct s3c24x0_timers *timers =s3c24x0_get_base_timers ();ulong tmr; -/* use PWM Timer 4 because it has no output */ -/* prescaler for Timer 4 is 16 */ -writel (0x0f00 , &timers->tcfg0); -if (timer_load_val ==0 ) { -/* -* for 10 ms clock period @ PCLK with 4 bit divider = 1/2 -* (default) and prescaler = 16. Should be 10390 -* @33.25MHz and 15625 @ 50 MHz
arch/arm/cpu/arm920t/s3c24x0/timer.c line 61
Quoted 10 lines
arch/arm/cpu/arm920t/s3c24x0/timer.c +2
-8-*/ - timer_load_val =get_PCLK () / (2 *16 *100 ); - timer_clk =get_PCLK () / (2 *16 ); - } -/* load value for 10 ms timeout */ - lastdec = timer_load_val; -writel (timer_load_val, &timers->tcntb4); -/* auto load, manual update of timer 4 */ +/* Set prescaler for Timer 4 */ +writel ((prescaler-1 ) <<8 , &timers->tcfg0);
Can we get rid of the magic numbers please?
arch/arm/cpu/arm920t/s3c24x0/timer.c line 64
Quoted 3 lines
arch/arm/cpu/arm920t/s3c24x0/timer.c +3
-0+ +/* Calculate timer freq, approx 100kHz @ PCLK=50MHz. */ + gd->timer_rate_hz =get_PCLK () / (2 * prescaler);
Can get_PCLK() be renamed to be lower-case only?
arch/arm/cpu/arm920t/s3c24x0/timer.c line 72
Quoted 8 lines
arch/arm/cpu/arm920t/s3c24x0/timer.c +7
-0+ +/* Set timer for 0.5s timeout (50000 ticks @ 10us ticks). */ + gd->timer_reset_value =50000 ; +writel (gd->timer_reset_value, &timers->tcntb4); + gd->lastdec = gd->timer_reset_value; + +/* Load the initial timer 4 count value using the manual update bit. */ tmr = (readl (&timers->tcon) & ~0x0700000 ) |0x0600000 ;
Magic values :-(
arch/arm/cpu/arm920t/s3c24x0/timer.c line 81
Quoted 11 lines
arch/arm/cpu/arm920t/s3c24x0/timer.c +4
-2writel (tmr, &timers->tcon); -/* auto load, start timer 4 */ + +/* Configure timer 4 for auto reload and start it. */ tmr = (tmr & ~0x0700000 ) |0x0500000 ;writel (tmr, &timers->tcon); - timestamp =0 ; + + gd->timestamp =0 ;return (0 );
return 0;
if you're cleaning this crap up, do it all at once ;-)
Quoted 137 lines
arch/arm/cpu/arm920t/s3c24x0/timer.c +27
-35}/* -* timer without interrupts +* Get the number of ticks (in CONFIG_SYS_HZ resolution) */ -ulong get_timer (ulong base) +unsigned long long get_ticks (void ) { -return get_timer_masked () - base; +return get_timer (0 ); } -void __udelay (unsigned long usec) +unsigned long get_timer_raw (void ) { -ulong tmo; -ulong start =get_ticks (); +ulong now =read_timer (); - tmo = usec /1000 ; - tmo *= (timer_load_val *100 ); - tmo /=1000 ; +if (gd->lastdec >= now) { +/* normal mode */ + gd->timestamp += gd->lastdec - now; + }else { +/* we have an overflow ... */ + gd->timestamp += gd->lastdec + gd->timer_reset_value - now; + } + gd->lastdec = now; -while ((ulong) (get_ticks () - start) < tmo) -/*NOP*/ ; +return gd->timestamp; } -ulong get_timer_masked (void ) +/* +* This function is derived from PowerPC code (timebase clock frequency). +* On ARM it returns the number of timer ticks per second. +*/ +ulong get_tbclk (void ) { -ulong tmr =get_ticks (); - -return tmr / (timer_clk /CONFIG_SYS_HZ ); +return CONFIG_SYS_HZ ; } -void udelay_masked (unsigned long usec) +ulong get_timer_masked (void ) { -ulong tmo; -ulong endtime; -signed long diff; - -if (usec >=1000 ) { - tmo = usec /1000 ; - tmo *= (timer_load_val *100 ); - tmo /=1000 ; - }else { - tmo = usec * (timer_load_val *100 ); - tmo /= (1000 *1000 ); - } +unsigned long tmr =get_timer_raw (); - endtime =get_ticks () + tmo; +return (tmr *CONFIG_SYS_HZ ) / gd->timer_rate_hz; +} -do { -ulong now =get_ticks (); - diff = endtime - now; - }while (diff >=0 ); +ulong get_timer (ulong base) +{ +return get_timer_masked () - base; } -/* -* This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value.
- */arch/arm/cpu/arm920t/s3c24x0/timer.c +8
-32-unsigned long long get_ticks (void ) +void __udelay (unsigned long usec) { -ulong now =READ_TIMER (); +unsigned long tmp; +unsigned long tmo; -if (lastdec >= now) { -/* normal mode */ - timestamp += lastdec - now; - }else { -/* we have an overflow ... */ - timestamp += lastdec + timer_load_val - now; - } - lastdec = now; +/* convert usec to ticks. */ + tmo = ((gd->timer_rate_hz /1000 ) * usec) /1000 ; -return timestamp; -} + tmp =get_timer_raw () + tmo;/* get current timestamp */ -/* -* This function is derived from PowerPC code (timebase clock frequency). -* On ARM it returns the number of timer ticks per second. -*/ -ulong get_tbclk (void ) -{ -ulong tbclk; - -#if defined(CONFIG_SMDK2400 ) - tbclk = timer_load_val *100 ; -#elif defined(CONFIG_SBC2410X ) || \ - defined(CONFIG_SMDK2410 ) || \ - defined(CONFIG_S3C2440 ) || \ - defined(CONFIG_VCMA9 ) - tbclk =CONFIG_SYS_HZ ; -#else -# error "tbclk not configured" -#endif - -return tbclk; +while (get_timer_raw () < tmp)/* loop till event */ +/*NOP*/ ; }/* arch/arm/include/asm/global_data.h +0
-0
arch/arm/include/asm/global_data.h typedef struct global_data { · line 73
Quoted 7 lines
arch/arm/include/asm/global_data.h +4
-0@@ -67,6 +67,10 @@ typedef struct global_data {#ifdef CONFIG_IXP425 unsigned long timestamp;#endif +#ifdef CONFIG_S3C24X0 +unsigned long lastdec; +unsigned long timestamp; +#endif
I wonder about this change ...
arch/arm/include/asm/global_data.h typedef struct global_data { · line 76
Quoted 3 lines
arch/arm/include/asm/global_data.h +0
-0unsigned long relocaddr;/* Start address of U-Boot in RAM */ phys_size_t ram_size;/* RAM size */ unsigned long mon_len;/* monitor len */
Cheers
PATCH 1/1 Update s3c24x0 timer implementation
Hi Marek Vasut,
Quoted 8 lines
Quoted 3 lines
I have attached an updated patch below which hopefully addresses the other issues you highlighted.
Hehe, you should RTFM ;-) http://www.denx.de/wiki/U-Boot/Patches
Generally, use git send-email to send the patch.
Thanks for your feedback. I have submitted an updated patch using git send-email. I think I got the formatting right this time. :)
Quoted 62 lines
Quoted 62 lines
The s3c24x0 timer has been updated to use the
global_datastruct. Restructured code based on othertimer.cfiles.
Updated comments and several parameters.Signed-off-by Mark Norman <[email protected]>---
?arch/arm/cpu/arm920t/s3c24x0/timer.c | ?155 +++++++++++++--------------------arch/arm/include/asm/global_data.h? | ?4 +
?2 files changed, 65 insertions(+), 94 deletions(-)arch/arm/cpu/arm920t/s3c24x0/timer.c +0
-0@@ -35,142 +35,109 @@?#include <
asm/io.h>
?#include <asm/arch/s3c24x0_cpu.h>arch/arm/cpu/arm920t/s3c24x0/timer.c +3
-4-int timer_load_val =0 ; -static ulong timer_clk; +DECLARE_GLOBAL_DATA_PTR ; -/* macro to read the 16 bit timer */ -static inline ulong READ_TIMER (void ) +/* Read the 16 bit timer */ +static inline ulong read_timer (void )?{
? ? ? structs3c24x0_timers*timers =s3c24x0_get_base_timers();? ? ? return
readl(&timers->tcnto4)&0xffff;
?}arch/arm/cpu/arm920t/s3c24x0/timer.c +0
-3-static ulong timestamp; -static ulong lastdec; -?int
timer_init(void)
?{
+ ? ? /*
+ ? ? ?* PWM Timer 4 is used because it has no output.
+ ? ? ?* Prescaler is hard fixed at 250, divider at 2.
+ ? ? ?* This generates a Timer clock frequency of 100kHz (@PCLK=50MHz) and
+ ? ? ?* therefore 10us timer ticks.
+ ? ? ?*/
+ ? ? const ulong prescaler = 250;
? ? ? structs3c24x0_timers*timers =s3c24x0_get_base_timers(); ? ? ? ulong tmr;- ? ? /* use PWM Timer 4 because it has no output */
- ? ? /* prescaler for Timer 4 is 16 */
- ? ?writel(0x0f00, &timers->tcfg0);
- ? ? if (timer_load_val== 0) {
- ? ? ? ? ? ? /*
- ? ? ? ? ? ? ?* for 10 ms clock period @ PCLK with 4 bit divider = 1/2
- ? ? ? ? ? ? ?* (default) and prescaler = 16. Should be 10390
- ? ? ? ? ? ? ?* @33.25MHz and 15625 @ 50 MHz
- ? ? ? ? ? ? ?*/
- ? ? ? ? ? ?timer_load_val=get_PCLK()/ (2 * 16 * 100);
- ? ? ? ? ? ?timer_clk=get_PCLK()/ (2 * 16);
- ? ? }
Quoted 8 lines
Quoted 6 lines
- ? ? /* load value for 10 ms timeout */
- ? ? lastdec =timer_load_val;
- ? ?writel(timer_load_val, &timers->tcntb4);
- ? ? /* auto load, manual update of timer 4 */
+ ? ? /* Set prescaler for Timer 4 */
+ ? ?writel((prescaler-1) << 8, &timers->tcfg0);Can we get rid of the magic numbers please?
I have declared some bitfields to remove the magic numbers.
Quoted 6 lines
Quoted 4 lines
+
+ ? ? /* Calculate timer freq, approx 100kHz @ PCLK=50MHz. */
+ ? ?gd->timer_rate_hz=get_PCLK()/ (2 * prescaler);Can
get_PCLK()be renamed to be lower-case only?
I haven't addressed this in my latest patch as it would be quite a large change that I though might be worthy of its own patch (there are several related functions get_FCLK, get_HCLK, etc. which could be updated at the same time).
Quoted 7 lines
Quoted 7 lines
arch/arm/include/asm/global_data.h +0
-0@@ -67,6 +67,10 @@ typedef ? ?struct ?global_data {?#ifdef
CONFIG_IXP425
Quoted 9 lines
arch/arm/include/asm/global_data.h typedef struct global_data { · line 73
Quoted 6 lines
? ? ? unsigned long ? timestamp;
?#endifarch/arm/include/asm/global_data.h +4
-0+#ifdef CONFIG_S3C24X0 + ? ? unsigned long ? lastdec; + ? ? unsigned long ? timestamp; +#endif I wonder about this change ...
The latest patch no longer creates new variables in the global_data struct and instead reuses some of the existing ones.
Any more feedback would be welcomed.
Cheers
Mark Norman
PATCH 1/1 Update s3c24x0 timer implementation
In reply to Mark NormanDear Mark Norman,
Quoted 12 lines · In message <CAJtrzLNz3TBBRHoNtHkuGci4YJZ9PLrJfvGaR_XdVbrdcprxbQ@mail.gmail.com>…
Dear Wolfgang Denk,
Thank you for your response.
Quoted 7 lines
Quoted 3 lines
=A0Since the .rel.text section is required by the relocation code, I assume that .bss global variables cannot be used until after relocation?
Why do you have to make such assumptions? =A0That's documented behaviour. =A0Didn't you RTFM?
Quoted 6 lines
I thought I had done a thorough search previously but after receiving your response I managed to find some of the details outlined in the README file.
I have attached an updated patch below which hopefully addresses the other issues you highlighted.
It seems you read my message only halfway through.
Quoted 6 lines
Kind Regards,
Mark Norman
Quoted 6 lines
The s3c24x0 timer has been updated to use the
global_datastruct. Restructured code based on othertimer.cfiles.
Updated comments and several parameters.Signed-off-by Mark Norman <[email protected]>---
I wrote before:
Then please submit a proper patch - these introductory comments don't belong into the commit message and should be moved into the comment section (below the "---" line).
Best regards,
Wolfgang Denk
Signature · 5 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Sometimes a feeling is all we humans have to go on. -- Kirk, "A Taste of Armageddon", stardate 3193.9