Commit 81f5d15c authored by Huacai Chen's avatar Huacai Chen
Browse files

LoongArch: Add adaptive CSR accessors for 32BIT/64BIT



32BIT platforms only have 32bit CSR/IOCSR registers, 64BIT platforms
have both 32bit/64bit CSR/IOCSR registers. Now there are both 32bit and
64bit CSR accessors:

csr_read32()/csr_write32()/csr_xchg32();
csr_read64()/csr_write64()/csr_xchg64();

Some CSR registers (address and timer registers) are 32bit length on
32BIT platform and 64bit length on 64BIT platform. To avoid #ifdefs here
and there, they need adaptive accessors, so we define and use:

csr_read()/csr_write()/csr_xchg();

IOCSR doesn't have a "natural length", which means a 64bit register can
be treated as two 32bit registers, so we just use two 32bit accessors to
emulate a 64bit accessors.

Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarJiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 79974cc3
Loading
Loading
Loading
Loading
+29 −17
Original line number Diff line number Diff line
@@ -182,6 +182,16 @@
#define csr_xchg32(val, mask, reg) __csrxchg_w(val, mask, reg)
#define csr_xchg64(val, mask, reg) __csrxchg_d(val, mask, reg)

#ifdef CONFIG_32BIT
#define csr_read(reg) csr_read32(reg)
#define csr_write(val, reg) csr_write32(val, reg)
#define csr_xchg(val, mask, reg) csr_xchg32(val, mask, reg)
#else
#define csr_read(reg) csr_read64(reg)
#define csr_write(val, reg) csr_write64(val, reg)
#define csr_xchg(val, mask, reg) csr_xchg64(val, mask, reg)
#endif

/* IOCSR */
#define iocsr_read32(reg) __iocsrrd_w(reg)
#define iocsr_read64(reg) __iocsrrd_d(reg)
@@ -1223,6 +1233,7 @@ static inline unsigned int get_csr_cpuid(void)
	return csr_read32(LOONGARCH_CSR_CPUID);
}

#ifdef CONFIG_64BIT
static inline void csr_any_send(unsigned int addr, unsigned int data,
				unsigned int data_mask, unsigned int cpu)
{
@@ -1234,6 +1245,7 @@ static inline void csr_any_send(unsigned int addr, unsigned int data,
	val |= ((uint64_t)data << IOCSR_ANY_SEND_BUF_SHIFT);
	iocsr_write64(val, LOONGARCH_IOCSR_ANY_SEND);
}
#endif

static inline unsigned int read_csr_excode(void)
{
@@ -1257,22 +1269,22 @@ static inline void write_csr_pagesize(unsigned int size)

static inline unsigned int read_csr_tlbrefill_pagesize(void)
{
	return (csr_read64(LOONGARCH_CSR_TLBREHI) & CSR_TLBREHI_PS) >> CSR_TLBREHI_PS_SHIFT;
	return (csr_read(LOONGARCH_CSR_TLBREHI) & CSR_TLBREHI_PS) >> CSR_TLBREHI_PS_SHIFT;
}

static inline void write_csr_tlbrefill_pagesize(unsigned int size)
{
	csr_xchg64(size << CSR_TLBREHI_PS_SHIFT, CSR_TLBREHI_PS, LOONGARCH_CSR_TLBREHI);
	csr_xchg(size << CSR_TLBREHI_PS_SHIFT, CSR_TLBREHI_PS, LOONGARCH_CSR_TLBREHI);
}

#define read_csr_asid()			csr_read32(LOONGARCH_CSR_ASID)
#define write_csr_asid(val)		csr_write32(val, LOONGARCH_CSR_ASID)
#define read_csr_entryhi()		csr_read64(LOONGARCH_CSR_TLBEHI)
#define write_csr_entryhi(val)		csr_write64(val, LOONGARCH_CSR_TLBEHI)
#define read_csr_entrylo0()		csr_read64(LOONGARCH_CSR_TLBELO0)
#define write_csr_entrylo0(val)		csr_write64(val, LOONGARCH_CSR_TLBELO0)
#define read_csr_entrylo1()		csr_read64(LOONGARCH_CSR_TLBELO1)
#define write_csr_entrylo1(val)		csr_write64(val, LOONGARCH_CSR_TLBELO1)
#define read_csr_entryhi()		csr_read(LOONGARCH_CSR_TLBEHI)
#define write_csr_entryhi(val)		csr_write(val, LOONGARCH_CSR_TLBEHI)
#define read_csr_entrylo0()		csr_read(LOONGARCH_CSR_TLBELO0)
#define write_csr_entrylo0(val)		csr_write(val, LOONGARCH_CSR_TLBELO0)
#define read_csr_entrylo1()		csr_read(LOONGARCH_CSR_TLBELO1)
#define write_csr_entrylo1(val)		csr_write(val, LOONGARCH_CSR_TLBELO1)
#define read_csr_ecfg()			csr_read32(LOONGARCH_CSR_ECFG)
#define write_csr_ecfg(val)		csr_write32(val, LOONGARCH_CSR_ECFG)
#define read_csr_estat()		csr_read32(LOONGARCH_CSR_ESTAT)
@@ -1282,20 +1294,20 @@ static inline void write_csr_tlbrefill_pagesize(unsigned int size)
#define read_csr_euen()			csr_read32(LOONGARCH_CSR_EUEN)
#define write_csr_euen(val)		csr_write32(val, LOONGARCH_CSR_EUEN)
#define read_csr_cpuid()		csr_read32(LOONGARCH_CSR_CPUID)
#define read_csr_prcfg1()		csr_read64(LOONGARCH_CSR_PRCFG1)
#define write_csr_prcfg1(val)		csr_write64(val, LOONGARCH_CSR_PRCFG1)
#define read_csr_prcfg2()		csr_read64(LOONGARCH_CSR_PRCFG2)
#define write_csr_prcfg2(val)		csr_write64(val, LOONGARCH_CSR_PRCFG2)
#define read_csr_prcfg3()		csr_read64(LOONGARCH_CSR_PRCFG3)
#define write_csr_prcfg3(val)		csr_write64(val, LOONGARCH_CSR_PRCFG3)
#define read_csr_prcfg1()		csr_read(LOONGARCH_CSR_PRCFG1)
#define write_csr_prcfg1(val)		csr_write(val, LOONGARCH_CSR_PRCFG1)
#define read_csr_prcfg2()		csr_read(LOONGARCH_CSR_PRCFG2)
#define write_csr_prcfg2(val)		csr_write(val, LOONGARCH_CSR_PRCFG2)
#define read_csr_prcfg3()		csr_read(LOONGARCH_CSR_PRCFG3)
#define write_csr_prcfg3(val)		csr_write(val, LOONGARCH_CSR_PRCFG3)
#define read_csr_stlbpgsize()		csr_read32(LOONGARCH_CSR_STLBPGSIZE)
#define write_csr_stlbpgsize(val)	csr_write32(val, LOONGARCH_CSR_STLBPGSIZE)
#define read_csr_rvacfg()		csr_read32(LOONGARCH_CSR_RVACFG)
#define write_csr_rvacfg(val)		csr_write32(val, LOONGARCH_CSR_RVACFG)
#define write_csr_tintclear(val)	csr_write32(val, LOONGARCH_CSR_TINTCLR)
#define read_csr_impctl1()		csr_read64(LOONGARCH_CSR_IMPCTL1)
#define write_csr_impctl1(val)		csr_write64(val, LOONGARCH_CSR_IMPCTL1)
#define write_csr_impctl2(val)		csr_write64(val, LOONGARCH_CSR_IMPCTL2)
#define read_csr_impctl1()		csr_read(LOONGARCH_CSR_IMPCTL1)
#define write_csr_impctl1(val)		csr_write(val, LOONGARCH_CSR_IMPCTL1)
#define write_csr_impctl2(val)		csr_write(val, LOONGARCH_CSR_IMPCTL2)

#define read_csr_perfctrl0()		csr_read64(LOONGARCH_CSR_PERFCTRL0)
#define read_csr_perfcntr0()		csr_read64(LOONGARCH_CSR_PERFCNTR0)
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ register unsigned long __my_cpu_offset __asm__("$r21");
static inline void set_my_cpu_offset(unsigned long off)
{
	__my_cpu_offset = off;
	csr_write64(off, PERCPU_BASE_KS);
	csr_write(off, PERCPU_BASE_KS);
}

#define __my_cpu_offset					\
+7 −0
Original line number Diff line number Diff line
@@ -298,8 +298,15 @@ static inline void cpu_probe_loongson(struct cpuinfo_loongarch *c, unsigned int
		return;
	}

#ifdef CONFIG_64BIT
	*vendor = iocsr_read64(LOONGARCH_IOCSR_VENDOR);
	*cpuname = iocsr_read64(LOONGARCH_IOCSR_CPUNAME);
#else
	*vendor = iocsr_read32(LOONGARCH_IOCSR_VENDOR) |
		(u64)iocsr_read32(LOONGARCH_IOCSR_VENDOR + 4) << 32;
	*cpuname = iocsr_read32(LOONGARCH_IOCSR_CPUNAME) |
		(u64)iocsr_read32(LOONGARCH_IOCSR_CPUNAME + 4) << 32;
#endif

	if (!__cpu_full_name[cpu]) {
		if (((char *)vendor)[0] == 0)
+8 −8
Original line number Diff line number Diff line
@@ -50,10 +50,10 @@ static int constant_set_state_oneshot(struct clock_event_device *evt)

	raw_spin_lock(&state_lock);

	timer_config = csr_read64(LOONGARCH_CSR_TCFG);
	timer_config = csr_read(LOONGARCH_CSR_TCFG);
	timer_config |= CSR_TCFG_EN;
	timer_config &= ~CSR_TCFG_PERIOD;
	csr_write64(timer_config, LOONGARCH_CSR_TCFG);
	csr_write(timer_config, LOONGARCH_CSR_TCFG);

	raw_spin_unlock(&state_lock);

@@ -70,7 +70,7 @@ static int constant_set_state_periodic(struct clock_event_device *evt)
	period = const_clock_freq / HZ;
	timer_config = period & CSR_TCFG_VAL;
	timer_config |= (CSR_TCFG_PERIOD | CSR_TCFG_EN);
	csr_write64(timer_config, LOONGARCH_CSR_TCFG);
	csr_write(timer_config, LOONGARCH_CSR_TCFG);

	raw_spin_unlock(&state_lock);

@@ -83,9 +83,9 @@ static int constant_set_state_shutdown(struct clock_event_device *evt)

	raw_spin_lock(&state_lock);

	timer_config = csr_read64(LOONGARCH_CSR_TCFG);
	timer_config = csr_read(LOONGARCH_CSR_TCFG);
	timer_config &= ~CSR_TCFG_EN;
	csr_write64(timer_config, LOONGARCH_CSR_TCFG);
	csr_write(timer_config, LOONGARCH_CSR_TCFG);

	raw_spin_unlock(&state_lock);

@@ -98,7 +98,7 @@ static int constant_timer_next_event(unsigned long delta, struct clock_event_dev

	delta &= CSR_TCFG_VAL;
	timer_config = delta | CSR_TCFG_EN;
	csr_write64(timer_config, LOONGARCH_CSR_TCFG);
	csr_write(timer_config, LOONGARCH_CSR_TCFG);

	return 0;
}
@@ -137,7 +137,7 @@ void save_counter(void)
void sync_counter(void)
{
	/* Ensure counter begin at 0 */
	csr_write64(init_offset, LOONGARCH_CSR_CNTC);
	csr_write(init_offset, LOONGARCH_CSR_CNTC);
}

int constant_clockevent_init(void)
@@ -235,7 +235,7 @@ void __init time_init(void)
	else
		const_clock_freq = calc_const_freq();

	init_offset = -(drdtime() - csr_read64(LOONGARCH_CSR_CNTC));
	init_offset = -(drdtime() - csr_read(LOONGARCH_CSR_CNTC));

	constant_clockevent_init();
	constant_clocksource_init();
+9 −6
Original line number Diff line number Diff line
@@ -625,7 +625,7 @@ asmlinkage void noinstr do_bce(struct pt_regs *regs)
	bool user = user_mode(regs);
	bool pie = regs_irqs_disabled(regs);
	unsigned long era = exception_era(regs);
	u64 badv = 0, lower = 0, upper = ULONG_MAX;
	unsigned long badv = 0, lower = 0, upper = ULONG_MAX;
	union loongarch_instruction insn;
	irqentry_state_t state = irqentry_enter(regs);

@@ -1070,10 +1070,13 @@ asmlinkage void noinstr do_reserved(struct pt_regs *regs)

asmlinkage void cache_parity_error(void)
{
	u32 merrctl = csr_read32(LOONGARCH_CSR_MERRCTL);
	unsigned long merrera = csr_read(LOONGARCH_CSR_MERRERA);

	/* For the moment, report the problem and hang. */
	pr_err("Cache error exception:\n");
	pr_err("csr_merrctl == %08x\n", csr_read32(LOONGARCH_CSR_MERRCTL));
	pr_err("csr_merrera == %016lx\n", csr_read64(LOONGARCH_CSR_MERRERA));
	pr_err("csr_merrctl == %08x\n", merrctl);
	pr_err("csr_merrera == %016lx\n", merrera);
	panic("Can't handle the cache error!");
}

@@ -1130,9 +1133,9 @@ static void configure_exception_vector(void)
	eentry    = (unsigned long)exception_handlers;
	tlbrentry = (unsigned long)exception_handlers + 80*VECSIZE;

	csr_write64(eentry, LOONGARCH_CSR_EENTRY);
	csr_write64(__pa(eentry), LOONGARCH_CSR_MERRENTRY);
	csr_write64(__pa(tlbrentry), LOONGARCH_CSR_TLBRENTRY);
	csr_write(eentry, LOONGARCH_CSR_EENTRY);
	csr_write(__pa(eentry), LOONGARCH_CSR_MERRENTRY);
	csr_write(__pa(tlbrentry), LOONGARCH_CSR_TLBRENTRY);
}

void per_cpu_trap_init(int cpu)
Loading