Re: [PATCH 3/9] arm: add call to CPU idle quirks handler

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 






On Fri, 26 Jun 2015, Arnd Bergmann wrote:

I doubt that the Kinetis has a custom version of the CPU core. Are you
sure that not all Cortex-M4 need this?

I'm not sure and I don't have any other Cortex-M SoC to verify that...
Without this hack, I'm experiencing following exception:

init started: BusyBox v1.17.0 (2015-03-27 08:16:34 CET)
~ # [    1.910000]
[    1.910000] Unhandled exception: IPSR = 00000006 LR = fffffff1
[ 1.910000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.1.0-next-20150623-00007-gf22ea1d-dirty #1
[    1.910000] Hardware name: Freescale Kinetis
[    1.910000] task: 082666f8 ti: 08264000 task.ti: 08264000
[    1.910000] PC is at arch_cpu_idle+0x14/0x1c
[    1.910000] LR is at arch_cpu_idle+0x13/0x1c
[    1.910000] pc : [<0800a928>]    lr : [<0800a927>]    psr: 6100000b
[    1.910000] sp : 08265f98  ip : 08264020  fp : 00000001
[    1.910000] r10: 0827433d  r9 : 00000000  r8 : 08266070
[    1.910000] r7 : 08272a88  r6 : 08266068  r5 : 00000000  r4 : 08266068
[    1.910000] r3 : 00000000  r2 : 08265fa0  r1 : 08264020  r0 : 08264000
[    1.910000] xPSR: 6100000b
[ 1.910000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.1.0-next-20150623-00007-gf22ea1d-dirty #1
[    1.910000] Hardware name: Freescale Kinetis
[ 1.910000] [<0800c5cd>] (unwind_backtrace) from [<0800b8b3>] (show_stack+0xb/0xc) [ 1.910000] [<0800b8b3>] (show_stack) from [<0800bd8b>] (__invalid_entry+0x4b/0x4c) [ 1.910000] [<0800bd8b>] (__invalid_entry) from [<ffffffff>] (0xffffffff)

Funny, it does not occur when JTAG is connected.


As long as the idle implementation depends only on the CPU core type,
it's easy to just define multiple .proc.info.init entries in the
same file, like we do in proc-v7.S.


I tried it and it works. This approach does not cause code duplication, but (comparing to arm_pm_idle-based approach) its long. Would something like this be accepted ever?

Note that contrary to proc-v7, there's no __v7m_proc macro, I had to define it in order to avoid another code duplication:

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8ccffee..da35b0b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -967,6 +967,7 @@ config ARCH_EFM32
 config ARCH_KINETIS
 	bool "Freescale Kinetis MCU"
 	depends on ARM_SINGLE_ARMV7M
+	select CPU_KINETIS
 	select ARMV7M_SYSTICK
 	select CLKSRC_KINETIS
 	select PINCTRL
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 85e374f..79792e9 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -234,6 +234,12 @@ static inline int cpu_is_xsc3(void)
 #define	cpu_is_xscale()	1
 #endif

+#if !defined(CONFIG_CPU_KINETIS)
+#define	cpu_is_kinetis()	0
+#else
+#define	cpu_is_kinetis()	1
+#endif
+
 /*
  * Marvell's PJ4 and PJ4B cores are based on V7 version,
  * but require a specical sequence for enabling coprocessors.
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
index 74be7c2..08583bb 100644
--- a/arch/arm/include/asm/glue-proc.h
+++ b/arch/arm/include/asm/glue-proc.h
@@ -230,6 +230,15 @@
 # endif
 #endif

+#ifdef CONFIG_CPU_KINETIS
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_kinetis
+# endif
+#endif
+
 #ifdef CONFIG_CPU_PJ4B
 # ifdef CPU_NAME
 #  undef  MULTI_CPU
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 121b580..ef59407 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -356,6 +356,11 @@ config CPU_PJ4B
 	bool
 	select CPU_V7

+# Freescale Kinetis
+config CPU_KINETIS
+	bool
+	select CPU_V7M
+
 # ARMv6
 config CPU_V6
bool "Support ARM V6 processor" if (!ARCH_MULTIPLATFORM || ARCH_MULTI_V6) && (ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX)
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
index ded9504..671374f 100644
--- a/arch/arm/mm/proc-v7m.S
+++ b/arch/arm/mm/proc-v7m.S
@@ -73,6 +73,30 @@ ENTRY(cpu_v7m_do_resume)
 ENDPROC(cpu_v7m_do_resume)
 #endif

+#ifdef CONFIG_CPU_KINETIS
+	globl_equ	cpu_kinetis_switch_mm,	cpu_v7m_switch_mm
+	globl_equ	cpu_kinetis_proc_init,	cpu_v7m_proc_init
+	globl_equ	cpu_kinetis_proc_fin, 	cpu_v7m_proc_fin
+	globl_equ	cpu_kinetis_reset,	cpu_v7m_reset
+ENTRY(cpu_kinetis_do_idle)
+	dsb
+	wfi
+	movw	r3, #:lower16:0xe0082000
+	movt	r3, #:upper16:0xe0082000
+	ldr	r0, [r3, #0]
+	orr	r2, r0, #0x85000000
+	str	r2, [r3, #0]
+	ret	lr
+ENDPROC(cpu_kinetis_do_idle)
+ globl_equ cpu_kinetis_dcache_clean_area, cpu_v7m_dcache_clean_area
+#ifdef CONFIG_ARM_CPU_SUSPEND
+	globl_equ	cpu_kinetis_do_suspend,	cpu_v7m_do_suspend
+	globl_equ	cpu_kinedis_do_resume,	cpu_v7m_do_resume
+#endif
+.globl	cpu_kinetis_suspend_size
+.equ	cpu_kinetis_suspend_size, cpu_v7m_suspend_size
+#endif
+
 	.section ".text.init", #alloc, #execinstr

 /*
@@ -140,6 +164,9 @@ __v7m_setup_stack:
 __v7m_setup_stack_top:

define_processor_functions v7m, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
+#ifdef CONFIG_CPU_KINETIS
+ define_processor_functions kinetis, dabort=nommu_early_abort, pabort=legacy_pabort, nommu=1
+#endif

 	.section ".rodata"
 	string cpu_arch_name, "armv7m"
@@ -148,23 +175,35 @@ __v7m_setup_stack_top:

 	.section ".proc.info.init", #alloc

-	/*
-	 * Match any ARMv7-M processor core.
-	 */
-	.type	__v7m_proc_info, #object
-__v7m_proc_info:
-	.long	0x000f0000		@ Required ID value
-	.long	0x000f0000		@ Mask for ID
+.macro __v7m_proc name, initfunc, proc_fns = v7m_processor_functions
.long 0 @ proc_info_list.__cpu_mm_mmu_flags .long 0 @ proc_info_list.__cpu_io_mmu_flags - initfn __v7m_setup, __v7m_proc_info @ proc_info_list.__cpu_flush
+	initfn	\initfunc, \name	@ proc_info_list.__cpu_flush
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT
 	.long	cpu_v7m_name
-	.long	v7m_processor_functions	@ proc_info_list.proc
+	.long	\proc_fns		@ proc_info_list.proc
 	.long	0			@ proc_info_list.tlb
 	.long	0			@ proc_info_list.user
 	.long	nop_cache_fns		@ proc_info_list.cache
-	.size	__v7m_proc_info, . - __v7m_proc_info
+.endm
+
+#ifdef CONFIG_CPU_KINETIS
+	.type   __v7m_kinetis_proc_info, #object
+__v7m_kinetis_proc_info:
+	.long	0x410fc240
+	.long	0xff0ffff0
+ __v7m_proc __v7m_kinetis_proc_info, __v7m_setup, proc_fns = kinetis_processor_functions
+	.size	__v7m_kinetis_proc_info, . - __v7m_kinetis_proc_info
+#endif

+	/*
+	 * Match any ARMv7-M processor core.
+	 */
+	.type	__v7m_proc_info, #object
+__v7m_proc_info:
+	.long	0x000f0000		@ Required ID value
+	.long	0x000f0000		@ Mask for ID
+	__v7m_proc __v7m_proc_info, __v7m_setup
+	.size	__v7m_proc_info, . - __v7m_proc_info


Works with and without JTAG connected.

(gdb) c
Continuing.
^C
Program received signal SIGTRAP, Trace/breakpoint trap.
cpu_kinetis_do_idle () at ../arch/arm/mm/proc-v7m.S:84
84		movw	r3, #:lower16:0xe0082000
(gdb) bt
#0  cpu_kinetis_do_idle () at ../arch/arm/mm/proc-v7m.S:84
#1  0x0800a4b0 in arch_cpu_idle () at ../arch/arm/kernel/process.c:72
#2  0x0802542a in cpuidle_idle_call (state=<value optimized out>)
    at ../kernel/sched/idle.c:157
#3 cpu_idle_loop (state=<value optimized out>) at ../kernel/sched/idle.c:253 #4 cpu_startup_entry (state=<value optimized out>) at ../kernel/sched/idle.c:301
#5  0x081bf816 in start_kernel () at ../init/main.c:683
#6  0x08008024 in stext () at ../arch/arm/kernel/head-nommu.S:85
(gdb)

Note dsb before wfi - I'm experiencing another (different) exception without it.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux