[PATCH 8/8] ARM: pxa: add iwmmx support for PJ4

Nicolas Pitre nico at fluxnic.net
Wed Nov 24 09:52:30 EST 2010


On Wed, 24 Nov 2010, Haojian Zhuang wrote:

> iwmmxt is used in XScale, XScale3, Mohawk and PJ4 core. But the instructions
> of accessing CP0 and CP1 is changed in PJ4. Append more files to support
> iwmmxt in PJ4 core.
> 
> Signed-off-by: Zhou Zhu <zzhu3 at marvell.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
> Cc: Eric Miao <eric.y.miao at gmail.com>
> Cc: Nicolas Pitre <nico at fluxnic.net>

Acked-by: Nicolas Pitre <nico at fluxnic.net>


> ---
>  arch/arm/Kconfig          |    4 +-
>  arch/arm/kernel/Makefile  |    1 +
>  arch/arm/kernel/iwmmxt.S  |   55 ++++++++++++++++++++------
>  arch/arm/kernel/pj4-cp0.c |   94 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 139 insertions(+), 15 deletions(-)
>  create mode 100644 arch/arm/kernel/pj4-cp0.c
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index a19a526..b0f25b0 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -999,8 +999,8 @@ source arch/arm/mm/Kconfig
>  
>  config IWMMXT
>  	bool "Enable iWMMXt support"
> -	depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK
> -	default y if PXA27x || PXA3xx || ARCH_MMP
> +	depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
> +	default y if PXA27x || PXA3xx || PXA95x || ARCH_MMP
>  	help
>  	  Enable support for iWMMXt context switching at run time if
>  	  running on a CPU that supports it.
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index 5b9b268..b0f11fa 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -50,6 +50,7 @@ AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
>  obj-$(CONFIG_CPU_XSCALE)	+= xscale-cp0.o
>  obj-$(CONFIG_CPU_XSC3)		+= xscale-cp0.o
>  obj-$(CONFIG_CPU_MOHAWK)	+= xscale-cp0.o
> +obj-$(CONFIG_CPU_PJ4)		+= pj4-cp0.o
>  obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
>  obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o
>  obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
> diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
> index b63b528..7fa3bb0 100644
> --- a/arch/arm/kernel/iwmmxt.S
> +++ b/arch/arm/kernel/iwmmxt.S
> @@ -19,6 +19,14 @@
>  #include <asm/thread_info.h>
>  #include <asm/asm-offsets.h>
>  
> +#if defined(CONFIG_CPU_PJ4)
> +#define PJ4(code...)		code
> +#define XSC(code...)
> +#else
> +#define PJ4(code...)
> +#define XSC(code...)		code
> +#endif
> +
>  #define MMX_WR0		 	(0x00)
>  #define MMX_WR1		 	(0x08)
>  #define MMX_WR2		 	(0x10)
> @@ -58,11 +66,17 @@
>  
>  ENTRY(iwmmxt_task_enable)
>  
> -	mrc	p15, 0, r2, c15, c1, 0
> -	tst	r2, #0x3			@ CP0 and CP1 accessible?
> +	XSC(mrc	p15, 0, r2, c15, c1, 0)
> +	PJ4(mrc p15, 0, r2, c1, c0, 2)
> +	@ CP0 and CP1 accessible?
> +	XSC(tst	r2, #0x3)
> +	PJ4(tst	r2, #0xf)
>  	movne	pc, lr				@ if so no business here
> -	orr	r2, r2, #0x3			@ enable access to CP0 and CP1
> -	mcr	p15, 0, r2, c15, c1, 0
> +	@ enable access to CP0 and CP1
> +	XSC(orr	r2, r2, #0x3)
> +	XSC(mcr	p15, 0, r2, c15, c1, 0)
> +	PJ4(orr	r2, r2, #0xf)
> +	PJ4(mcr	p15, 0, r2, c1, c0, 2)
>  
>  	ldr	r3, =concan_owner
>  	add	r0, r10, #TI_IWMMXT_STATE	@ get task Concan save area
> @@ -179,17 +193,26 @@ ENTRY(iwmmxt_task_disable)
>  	teqne	r1, r2				@ or specified one?
>  	bne	1f				@ no: quit
>  
> -	mrc	p15, 0, r4, c15, c1, 0
> -	orr	r4, r4, #0x3			@ enable access to CP0 and CP1
> -	mcr	p15, 0, r4, c15, c1, 0
> +	@ enable access to CP0 and CP1
> +	XSC(mrc	p15, 0, r4, c15, c1, 0)
> +	XSC(orr	r4, r4, #0xf)
> +	XSC(mcr	p15, 0, r4, c15, c1, 0)
> +	PJ4(mrc p15, 0, r4, c1, c0, 2)
> +	PJ4(orr	r4, r4, #0x3)
> +	PJ4(mcr	p15, 0, r4, c1, c0, 2)
> +
>  	mov	r0, #0				@ nothing to load
>  	str	r0, [r3]			@ no more current owner
>  	mrc	p15, 0, r2, c2, c0, 0
>  	mov	r2, r2				@ cpwait
>  	bl	concan_save
>  
> -	bic	r4, r4, #0x3			@ disable access to CP0 and CP1
> -	mcr	p15, 0, r4, c15, c1, 0
> +	@ disable access to CP0 and CP1
> +	XSC(bic	r4, r4, #0x3)
> +	XSC(mcr	p15, 0, r4, c15, c1, 0)
> +	PJ4(bic	r4, r4, #0xf)
> +	PJ4(mcr	p15, 0, r4, c1, c0, 2)
> +
>  	mrc	p15, 0, r2, c2, c0, 0
>  	mov	r2, r2				@ cpwait
>  
> @@ -277,8 +300,11 @@ ENTRY(iwmmxt_task_restore)
>   */
>  ENTRY(iwmmxt_task_switch)
>  
> -	mrc	p15, 0, r1, c15, c1, 0
> -	tst	r1, #0x3			@ CP0 and CP1 accessible?
> +	XSC(mrc	p15, 0, r1, c15, c1, 0)
> +	PJ4(mrc	p15, 0, r1, c1, c0, 2)
> +	@ CP0 and CP1 accessible?
> +	XSC(tst	r1, #0x3)
> +	PJ4(tst	r1, #0xf)
>  	bne	1f				@ yes: block them for next task
>  
>  	ldr	r2, =concan_owner
> @@ -287,8 +313,11 @@ ENTRY(iwmmxt_task_switch)
>  	teq	r2, r3				@ next task owns it?
>  	movne	pc, lr				@ no: leave Concan disabled
>  
> -1:	eor	r1, r1, #3			@ flip Concan access
> -	mcr	p15, 0, r1, c15, c1, 0
> +1:	@ flip Conan access
> +	XSC(eor	r1, r1, #0x3)
> +	XSC(mcr	p15, 0, r1, c15, c1, 0)
> +	PJ4(eor r1, r1, #0xf)
> +	PJ4(mcr	p15, 0, r1, c1, c0, 2)
>  
>  	mrc	p15, 0, r1, c2, c0, 0
>  	sub	pc, lr, r1, lsr #32		@ cpwait and return
> diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c
> new file mode 100644
> index 0000000..a4b1b07
> --- /dev/null
> +++ b/arch/arm/kernel/pj4-cp0.c
> @@ -0,0 +1,94 @@
> +/*
> + * linux/arch/arm/kernel/pj4-cp0.c
> + *
> + * PJ4 iWMMXt coprocessor context switching and handling
> + *
> + * Copyright (c) 2010 Marvell International Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/signal.h>
> +#include <linux/sched.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <asm/thread_notify.h>
> +
> +static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
> +{
> +	struct thread_info *thread = t;
> +
> +	switch (cmd) {
> +	case THREAD_NOTIFY_FLUSH:
> +		/*
> +		 * flush_thread() zeroes thread->fpstate, so no need
> +		 * to do anything here.
> +		 *
> +		 * FALLTHROUGH: Ensure we don't try to overwrite our newly
> +		 * initialised state information on the first fault.
> +		 */
> +
> +	case THREAD_NOTIFY_EXIT:
> +		iwmmxt_task_release(thread);
> +		break;
> +
> +	case THREAD_NOTIFY_SWITCH:
> +		iwmmxt_task_switch(thread);
> +		break;
> +	}
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block iwmmxt_notifier_block = {
> +	.notifier_call	= iwmmxt_do,
> +};
> +
> +
> +static u32 __init pj4_cp_access_read(void)
> +{
> +	u32 value;
> +
> +	__asm__ __volatile__ (
> +		"mrc	p15, 0, %0, c1, c0, 2\n\t"
> +		: "=r" (value));
> +	return value;
> +}
> +
> +static void __init pj4_cp_access_write(u32 value)
> +{
> +	u32 temp;
> +
> +	__asm__ __volatile__ (
> +		"mcr	p15, 0, %1, c1, c0, 2\n\t"
> +		"mrc	p15, 0, %0, c1, c0, 2\n\t"
> +		"mov	%0, %0\n\t"
> +		"sub	pc, pc, #4\n\t"
> +		: "=r" (temp) : "r" (value));
> +}
> +
> +
> +/*
> + * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
> + * switch code handle iWMMXt context switching.
> + */
> +static int __init pj4_cp0_init(void)
> +{
> +	u32 cp_access;
> +
> +	cp_access = pj4_cp_access_read() & ~0xf;
> +	pj4_cp_access_write(cp_access);
> +
> +	printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n");
> +	elf_hwcap |= HWCAP_IWMMXT;
> +	thread_register_notifier(&iwmmxt_notifier_block);
> +
> +	return 0;
> +}
> +
> +late_initcall(pj4_cp0_init);
> -- 
> 1.5.6.5
> 



More information about the linux-arm-kernel mailing list