Skip to contentSkip to conversation

Update s3c24x0 timer implementation

PATCH New Mark Norman 3 participants 6 messages Oct 23, 2011 – Oct 31, 2011 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

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 other
timer.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
#1 lore raw

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.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 other
timer.c files. 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), 1943
#2 lore raw

PATCH 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
#3 lore raw

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_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(-)
arch/arm/cpu/arm920t/s3c24x0/timer.c +10 -15
index 9571870..5695c62 100644
@@ -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 -2
 	writel(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
index fac98d5..b836915 100644

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 -0
 	unsigned long	relocaddr;	/* Start address of U-Boot in RAM */
 	phys_size_t	ram_size;	/* RAM size */
 	unsigned long	mon_len;	/* monitor len */

Cheers

#4 lore raw

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_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(-)

arch/arm/cpu/arm920t/s3c24x0/timer.c +0 -0
index 9571870..5695c62 100644
@@ -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)

?{
? ? ? struct s3c24x0_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;
? ? ? 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
- ? ? ? ? ? ? ?*/
- ? ? ? ? ? ? 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
index fac98d5..b836915 100644
@@ -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;
?#endif

arch/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

#5 lore raw

PATCH 1/1 Update s3c24x0 timer implementation

In reply to Mark Norman

Dear 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_data struct. Restructured code based on other timer.c files.
Updated comments and several parameters.

---

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