diff mbox

[1/6] ARM: tegra: add an assembly marco to check Tegra SoC ID

Message ID 1368613644-11863-2-git-send-email-josephl@nvidia.com (mailing list archive)
State New, archived
Headers show

Commit Message

Joseph Lo May 15, 2013, 10:27 a.m. UTC
There are some Tegra SoC ID checking code around the low level assembly
code. Adding a marco to replace them. For the single image to support all
the Tegra series, we may also need the marco in other common code. So we
make it become a marco for the usage.

Signed-off-by: Joseph Lo <josephl@nvidia.com>
---
 arch/arm/mach-tegra/fuse.h          | 22 ++++++++++++----------
 arch/arm/mach-tegra/reset-handler.S | 24 +++++++-----------------
 arch/arm/mach-tegra/sleep.h         |  9 +++++++++
 3 files changed, 28 insertions(+), 27 deletions(-)

Comments

Stephen Warren May 15, 2013, 10:43 p.m. UTC | #1
On 05/15/2013 04:27 AM, Joseph Lo wrote:
> There are some Tegra SoC ID checking code around the low level assembly
> code. Adding a marco to replace them. For the single image to support all
> the Tegra series, we may also need the marco in other common code. So we
> make it become a marco for the usage.

I'm not sure this patch doesn't obfuscate the code too much. The big
issue I see is:

> @@ -115,13 +112,9 @@ ENTRY(__tegra_cpu_reset_handler)
>  
>  	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
>  
> -	mov32	r6, TEGRA_APB_MISC_BASE
> -	ldr	r6, [r6, #APB_MISC_GP_HIDREV]
> -	and	r6, r6, #0xff00
> -#ifdef CONFIG_ARCH_TEGRA_2x_SOC
> -t20_check:
> -	cmp	r6, #(0x20 << 8)
> +	tegra_check_soc_id TEGRA20, TEGRA_APB_MISC_BASE, r6, r5

Here, we replace all the code with the new macro, ...

>  #ifdef CONFIG_ARCH_TEGRA_2x_SOC
>  	/* Are we on Tegra20? */
> -	cmp	r6, #(0x20 << 8)
> +	cmp	r6, #(TEGRA20 << 8)

But here we still have to write out the cmp instructions.

It may be reasonable to create a macro to read/mask/shift the SoC ID,
similar to the existing cpu_id macro, i.e. roughly:

/* Macro to check Tegra revision */
+#define APB_MISC_GP_HIDREV	0x804
+.macro tegra_soc_id base, tmp1, tmp2
+	mov32	\tmp2, \base
+	ldr	\tmp1, [\tmp2, #APB_MISC_GP_HIDREV]
+	and	\tmp1, \tmp1, #0xff00
+.endm

Also, I wonder:

(a) why the need to pass TEGRA_APB_MISC_BASE into the macro; can't the
macro just hard-code that value since it's always the same?

(b) Why need two registers passed to the macro. At least one of the code
segments you've replaced with the macro uses a single register instead:

-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r6, [r6, #APB_MISC_GP_HIDREV]
-	and	r6, r6, #0xff00

Wouldn't that be a better implementation of the macro? I don't think
relying on \tmp2 containing "base" after the macro invocation would be a
good idea, since that's rather like looking inside the black box.
Joseph Lo May 16, 2013, 10:09 a.m. UTC | #2
On Thu, 2013-05-16 at 06:43 +0800, Stephen Warren wrote:
> On 05/15/2013 04:27 AM, Joseph Lo wrote:
> > There are some Tegra SoC ID checking code around the low level assembly
> > code. Adding a marco to replace them. For the single image to support all
> > the Tegra series, we may also need the marco in other common code. So we
> > make it become a marco for the usage.
> 
> I'm not sure this patch doesn't obfuscate the code too much. The big
> issue I see is:
> 
> > @@ -115,13 +112,9 @@ ENTRY(__tegra_cpu_reset_handler)
> >  
> >  	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
> >  
> > -	mov32	r6, TEGRA_APB_MISC_BASE
> > -	ldr	r6, [r6, #APB_MISC_GP_HIDREV]
> > -	and	r6, r6, #0xff00
> > -#ifdef CONFIG_ARCH_TEGRA_2x_SOC
> > -t20_check:
> > -	cmp	r6, #(0x20 << 8)
> > +	tegra_check_soc_id TEGRA20, TEGRA_APB_MISC_BASE, r6, r5
> 
> Here, we replace all the code with the new macro, ...
> 
> >  #ifdef CONFIG_ARCH_TEGRA_2x_SOC
> >  	/* Are we on Tegra20? */
> > -	cmp	r6, #(0x20 << 8)
> > +	cmp	r6, #(TEGRA20 << 8)
> 
> But here we still have to write out the cmp instructions.
> 
The marco did "cmp" once and move the soc_id into r6. But the flags may
be changed after running some other codes, we need to "cmp" again to get
the correct flag.

> It may be reasonable to create a macro to read/mask/shift the SoC ID,
> similar to the existing cpu_id macro, i.e. roughly:
> 
> /* Macro to check Tegra revision */
> +#define APB_MISC_GP_HIDREV	0x804
> +.macro tegra_soc_id base, tmp1, tmp2
> +	mov32	\tmp2, \base
> +	ldr	\tmp1, [\tmp2, #APB_MISC_GP_HIDREV]
> +	and	\tmp1, \tmp1, #0xff00
> +.endm
> 
> Also, I wonder:
> 
> (a) why the need to pass TEGRA_APB_MISC_BASE into the macro; can't the
> macro just hard-code that value since it's always the same?
> 
Because this marco will be used in virtual address space too, I need to
pass different base addr here.

> (b) Why need two registers passed to the macro. At least one of the code
> segments you've replaced with the macro uses a single register instead:
> 
> -	mov32	r6, TEGRA_APB_MISC_BASE
> -	ldr	r6, [r6, #APB_MISC_GP_HIDREV]
> -	and	r6, r6, #0xff00
> 
> Wouldn't that be a better implementation of the macro? I don't think
> relying on \tmp2 containing "base" after the macro invocation would be a
> good idea, since that's rather like looking inside the black box.

OK. I can remove one tmp register here.
Stephen Warren May 16, 2013, 6:21 p.m. UTC | #3
On 05/16/2013 04:09 AM, Joseph Lo wrote:
> On Thu, 2013-05-16 at 06:43 +0800, Stephen Warren wrote:
>> On 05/15/2013 04:27 AM, Joseph Lo wrote:
>>> There are some Tegra SoC ID checking code around the low level assembly
>>> code. Adding a marco to replace them. For the single image to support all
>>> the Tegra series, we may also need the marco in other common code. So we
>>> make it become a marco for the usage.
>>
>> I'm not sure this patch doesn't obfuscate the code too much. The big
>> issue I see is:
>>
>>> @@ -115,13 +112,9 @@ ENTRY(__tegra_cpu_reset_handler)
>>>  
>>>  	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
>>>  
>>> -	mov32	r6, TEGRA_APB_MISC_BASE
>>> -	ldr	r6, [r6, #APB_MISC_GP_HIDREV]
>>> -	and	r6, r6, #0xff00
>>> -#ifdef CONFIG_ARCH_TEGRA_2x_SOC
>>> -t20_check:
>>> -	cmp	r6, #(0x20 << 8)
>>> +	tegra_check_soc_id TEGRA20, TEGRA_APB_MISC_BASE, r6, r5
>>
>> Here, we replace all the code with the new macro, ...
>>
>>>  #ifdef CONFIG_ARCH_TEGRA_2x_SOC
>>>  	/* Are we on Tegra20? */
>>> -	cmp	r6, #(0x20 << 8)
>>> +	cmp	r6, #(TEGRA20 << 8)
>>
>> But here we still have to write out the cmp instructions.
>>
> The marco did "cmp" once and move the soc_id into r6. But the flags may
> be changed after running some other codes, we need to "cmp" again to get
> the correct flag.

Yes, I understand that. The issue is that writing the macro didn't
remove all the code, so it seems like it'd be best if the macro only
included the common code, and anything that needs to be repeated at each
test site not be part of the macro.
diff mbox

Patch

diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index aacc00d..def7968 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -19,16 +19,6 @@ 
 #ifndef __MACH_TEGRA_FUSE_H
 #define __MACH_TEGRA_FUSE_H
 
-enum tegra_revision {
-	TEGRA_REVISION_UNKNOWN = 0,
-	TEGRA_REVISION_A01,
-	TEGRA_REVISION_A02,
-	TEGRA_REVISION_A03,
-	TEGRA_REVISION_A03p,
-	TEGRA_REVISION_A04,
-	TEGRA_REVISION_MAX,
-};
-
 #define SKU_ID_T20	8
 #define SKU_ID_T25SE	20
 #define SKU_ID_AP25	23
@@ -40,6 +30,17 @@  enum tegra_revision {
 #define TEGRA30		0x30
 #define TEGRA114	0x35
 
+#ifndef __ASSEMBLY__
+enum tegra_revision {
+	TEGRA_REVISION_UNKNOWN = 0,
+	TEGRA_REVISION_A01,
+	TEGRA_REVISION_A02,
+	TEGRA_REVISION_A03,
+	TEGRA_REVISION_A03p,
+	TEGRA_REVISION_A04,
+	TEGRA_REVISION_MAX,
+};
+
 extern int tegra_sku_id;
 extern int tegra_cpu_process_id;
 extern int tegra_core_process_id;
@@ -72,5 +73,6 @@  void tegra114_init_speedo_data(void);
 #else
 static inline void tegra114_init_speedo_data(void) {}
 #endif
+#endif /* __ASSEMBLY__ */
 
 #endif
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index e6de88a..525f1b9 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -22,11 +22,11 @@ 
 #include <asm/hardware/cache-l2x0.h>
 
 #include "flowctrl.h"
+#include "fuse.h"
 #include "iomap.h"
 #include "reset.h"
 #include "sleep.h"
 
-#define APB_MISC_GP_HIDREV	0x804
 #define PMC_SCRATCH41	0x140
 
 #define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
@@ -49,10 +49,7 @@  ENTRY(tegra_resume)
 
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 	/* Are we on Tegra20? */
-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
-	and	r0, r0, #0xff00
-	cmp	r0, #(0x20 << 8)
+	tegra_check_soc_id TEGRA20, TEGRA_APB_MISC_BASE, r6, r7
 	beq	1f				@ Yes
 	/* Clear the flow controller flags for this CPU. */
 	mov32	r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR	@ CPU0 CSR
@@ -115,13 +112,9 @@  ENTRY(__tegra_cpu_reset_handler)
 
 	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
 
-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r6, [r6, #APB_MISC_GP_HIDREV]
-	and	r6, r6, #0xff00
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-t20_check:
-	cmp	r6, #(0x20 << 8)
+	tegra_check_soc_id TEGRA20, TEGRA_APB_MISC_BASE, r6, r5
 	bne	after_t20_check
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 t20_errata:
 	# Tegra20 is a Cortex-A9 r1p1
 	mrc	p15, 0, r0, c1, c0, 0   @ read system control register
@@ -132,8 +125,8 @@  t20_errata:
 	orr	r0, r0, #1 << 11        @ erratum 751472
 	mcr	p15, 0, r0, c15, c0, 1  @ write diagnostic register
 	b	after_errata
-after_t20_check:
 #endif
+after_t20_check:
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 t30_check:
 	cmp	r6, #(0x30 << 8)
@@ -163,7 +156,7 @@  after_errata:
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 	/* Are we on Tegra20? */
-	cmp	r6, #(0x20 << 8)
+	cmp	r6, #(TEGRA20 << 8)
 	bne	1f
 	/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
 	mov32	r5, TEGRA_PMC_BASE
@@ -210,10 +203,7 @@  __die:
 	mov32	r7, TEGRA_CLK_RESET_BASE
 
 	/* Are we on Tegra20? */
-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
-	and	r0, r0, #0xff00
-	cmp	r0, #(0x20 << 8)
+	cmp	r6, #(TEGRA20 << 8)
 	bne	1f
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 2080fb1..7e9c9fe 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -85,6 +85,15 @@ 
 	dsb
 .endm
 
+/* Macro to check Tegra revision */
+#define APB_MISC_GP_HIDREV	0x804
+.macro tegra_check_soc_id rev, base, tmp1, tmp2
+	mov32	\tmp2, \base
+	ldr	\tmp1, [\tmp2, #APB_MISC_GP_HIDREV]
+	and	\tmp1, \tmp1, #0xff00
+	cmp	\tmp1, #(\rev << 8)
+.endm
+
 /* Macro to resume & re-enable L2 cache */
 #ifndef L2X0_CTRL_EN
 #define L2X0_CTRL_EN	1