Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d2170be authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Paul Mackerras
Browse files

powerpc/4xx: Extended DCR support v2



This adds supports to the "extended" DCR addressing via the indirect
mfdcrx/mtdcrx instructions supported by some 4xx cores (440H6 and
later).

I enabled the feature for now only on AMCC 460 chips.

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: default avatarJosh Boyer <jwboyer@linux.vnet.ibm.com>
Acked-by: default avatarKumar Gala <galak@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent fecba962
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ extern const char *powerpc_base_platform;
#define CPU_FTR_NEED_PAIRED_STWCX	ASM_CONST(0x0000000004000000)
#define CPU_FTR_LWSYNC			ASM_CONST(0x0000000008000000)
#define CPU_FTR_NOEXECUTE		ASM_CONST(0x0000000010000000)
#define CPU_FTR_INDEXED_DCR		ASM_CONST(0x0000000020000000)

/*
 * Add the 64-bit processor unique features in the top half of the word;
@@ -369,6 +370,8 @@ extern const char *powerpc_base_platform;
#define CPU_FTRS_8XX	(CPU_FTR_USE_TB)
#define CPU_FTRS_40X	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_44X	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
#define CPU_FTRS_440x6	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE | \
	    CPU_FTR_INDEXED_DCR)
#define CPU_FTRS_E200	(CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \
	    CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \
	    CPU_FTR_UNIFIED_ID_CACHE | CPU_FTR_NOEXECUTE)
@@ -455,7 +458,7 @@ enum {
	    CPU_FTRS_40X |
#endif
#ifdef CONFIG_44x
	    CPU_FTRS_44X |
	    CPU_FTRS_44X | CPU_FTRS_440x6 |
#endif
#ifdef CONFIG_E200
	    CPU_FTRS_E200 |
@@ -495,7 +498,7 @@ enum {
	    CPU_FTRS_40X &
#endif
#ifdef CONFIG_44x
	    CPU_FTRS_44X &
	    CPU_FTRS_44X & CPU_FTRS_440x6 &
#endif
#ifdef CONFIG_E200
	    CPU_FTRS_E200 &
+51 −12
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#ifndef __ASSEMBLY__

#include <linux/spinlock.h>
#include <asm/cputable.h>

typedef struct {
	unsigned int base;
@@ -39,23 +40,45 @@ static inline bool dcr_map_ok_native(dcr_host_native_t host)
#define dcr_read_native(host, dcr_n)		mfdcr(dcr_n + host.base)
#define dcr_write_native(host, dcr_n, value)	mtdcr(dcr_n + host.base, value)

/* Device Control Registers */
void __mtdcr(int reg, unsigned int val);
unsigned int __mfdcr(int reg);
/* Table based DCR accessors */
extern void __mtdcr(unsigned int reg, unsigned int val);
extern unsigned int __mfdcr(unsigned int reg);

/* mfdcrx/mtdcrx instruction based accessors. We hand code
 * the opcodes in order not to depend on newer binutils
 */
static inline unsigned int mfdcrx(unsigned int reg)
{
	unsigned int ret;
	asm volatile(".long 0x7c000206 | (%0 << 21) | (%1 << 16)"
		     : "=r" (ret) : "r" (reg));
	return ret;
}

static inline void mtdcrx(unsigned int reg, unsigned int val)
{
	asm volatile(".long 0x7c000306 | (%0 << 21) | (%1 << 16)"
		     : : "r" (val), "r" (reg));
}

#define mfdcr(rn)						\
	({unsigned int rval;					\
	if (__builtin_constant_p(rn))				\
	if (__builtin_constant_p(rn) && rn < 1024)		\
		asm volatile("mfdcr %0," __stringify(rn)	\
		              : "=r" (rval));			\
	else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR)))	\
		rval = mfdcrx(rn);				\
	else							\
		rval = __mfdcr(rn);				\
	rval;})

#define mtdcr(rn, v)						\
do {								\
	if (__builtin_constant_p(rn))				\
	if (__builtin_constant_p(rn) && rn < 1024)		\
		asm volatile("mtdcr " __stringify(rn) ",%0"	\
			      : : "r" (v)); 			\
	else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR)))	\
		mtdcrx(rn, v);					\
	else							\
		__mtdcr(rn, v);					\
} while (0)
@@ -69,8 +92,13 @@ static inline unsigned __mfdcri(int base_addr, int base_data, int reg)
	unsigned int val;

	spin_lock_irqsave(&dcr_ind_lock, flags);
	if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) {
		mtdcrx(base_addr, reg);
		val = mfdcrx(base_data);
	} else {
		__mtdcr(base_addr, reg);
		val = __mfdcr(base_data);
	}
	spin_unlock_irqrestore(&dcr_ind_lock, flags);
	return val;
}
@@ -81,8 +109,13 @@ static inline void __mtdcri(int base_addr, int base_data, int reg,
	unsigned long flags;

	spin_lock_irqsave(&dcr_ind_lock, flags);
	if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) {
		mtdcrx(base_addr, reg);
		mtdcrx(base_data, val);
	} else {
		__mtdcr(base_addr, reg);
		__mtdcr(base_data, val);
	}
	spin_unlock_irqrestore(&dcr_ind_lock, flags);
}

@@ -93,9 +126,15 @@ static inline void __dcri_clrset(int base_addr, int base_data, int reg,
	unsigned int val;

	spin_lock_irqsave(&dcr_ind_lock, flags);
	if (cpu_has_feature(CPU_FTR_INDEXED_DCR)) {
		mtdcrx(base_addr, reg);
		val = (mfdcrx(base_data) & ~clr) | set;
		mtdcrx(base_data, val);
	} else {
		__mtdcr(base_addr, reg);
		val = (__mfdcr(base_data) & ~clr) | set;
		__mtdcr(base_data, val);
	}
	spin_unlock_irqrestore(&dcr_ind_lock, flags);
}

+2 −2
Original line number Diff line number Diff line
@@ -1509,7 +1509,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.pvr_mask		= 0xffff0002,
		.pvr_value		= 0x13020002,
		.cpu_name		= "460EX",
		.cpu_features		= CPU_FTRS_44X,
		.cpu_features		= CPU_FTRS_440x6,
		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
		.icache_bsize		= 32,
		.dcache_bsize		= 32,
@@ -1521,7 +1521,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
		.pvr_mask		= 0xffff0002,
		.pvr_value		= 0x13020000,
		.cpu_name		= "460GT",
		.cpu_features		= CPU_FTRS_44X,
		.cpu_features		= CPU_FTRS_440x6,
		.cpu_user_features	= COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
		.icache_bsize		= 32,
		.dcache_bsize		= 32,
+7 −1
Original line number Diff line number Diff line
@@ -11,14 +11,20 @@

#include <asm/ppc_asm.h>
#include <asm/processor.h>
#include <asm/bug.h>

#define DCR_ACCESS_PROLOG(table) \
	cmpli	cr0,r3,1024;	 \
	rlwinm  r3,r3,4,18,27;   \
	lis     r5,table@h;      \
	ori     r5,r5,table@l;   \
	add     r3,r3,r5;        \
	bge-	1f;		 \
	mtctr   r3;              \
	bctr
	bctr;			 \
1:	trap;			 \
	EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0;	\
	blr

_GLOBAL(__mfdcr)
	DCR_ACCESS_PROLOG(__mfdcr_table)