Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * linux/arch/arm/kernel/xscale-cp0.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * XScale DSP and iWMMXt coprocessor context switching and handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <asm/thread_notify.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <asm/cputype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) asm("	.arch armv5te\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) static inline void dsp_save_state(u32 *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 		"mrrc	p0, 0, %0, %1, c0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 		: "=r" (state[0]), "=r" (state[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static inline void dsp_load_state(u32 *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		"mcrr	p0, 0, %0, %1, c0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 		: : "r" (state[0]), "r" (state[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static int dsp_do(struct notifier_block *self, unsigned long cmd, void *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct thread_info *thread = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	case THREAD_NOTIFY_FLUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		thread->cpu_context.extra[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		thread->cpu_context.extra[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	case THREAD_NOTIFY_SWITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		dsp_save_state(current_thread_info()->cpu_context.extra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		dsp_load_state(thread->cpu_context.extra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) static struct notifier_block dsp_notifier_block = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	.notifier_call	= dsp_do,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #ifdef CONFIG_IWMMXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	struct thread_info *thread = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	case THREAD_NOTIFY_FLUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		 * flush_thread() zeroes thread->fpstate, so no need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		 * to do anything here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		 * FALLTHROUGH: Ensure we don't try to overwrite our newly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		 * initialised state information on the first fault.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	case THREAD_NOTIFY_EXIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		iwmmxt_task_release(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	case THREAD_NOTIFY_SWITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		iwmmxt_task_switch(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) static struct notifier_block iwmmxt_notifier_block = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	.notifier_call	= iwmmxt_do,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static u32 __init xscale_cp_access_read(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		"mrc	p15, 0, %0, c15, c1, 0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		: "=r" (value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void __init xscale_cp_access_write(u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		"mcr	p15, 0, %1, c15, c1, 0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		"mrc	p15, 0, %0, c15, c1, 0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		"mov	%0, %0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		"sub	pc, pc, #4\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		: "=r" (temp) : "r" (value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  * Detect whether we have a MAC coprocessor (40 bit register) or an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * iWMMXt coprocessor (64 bit registers) by loading 00000100:00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * into a coprocessor register and reading it back, and checking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * whether the upper word survived intact.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int __init cpu_has_iwmmxt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	u32 lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	u32 hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	 * This sequence is interpreted by the DSP coprocessor as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	 *	mar	acc0, %2, %3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	 *	mra	%0, %1, acc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	 * And by the iWMMXt coprocessor as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	 *	tmcrr	wR0, %2, %3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	 *	tmrrc	%0, %1, wR0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		"mcrr	p0, 0, %2, %3, c0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		"mrrc	p0, 0, %0, %1, c0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		: "=r" (lo), "=r" (hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		: "r" (0), "r" (0x100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	return !!hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * If we detect that the CPU has iWMMXt (and CONFIG_IWMMXT=y), we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  * disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  * switch code handle iWMMXt context switching.  If on the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  * hand the CPU has a DSP coprocessor, we keep access to CP0 enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * all the time, and save/restore acc0 on context switch in non-lazy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  * fashion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int __init xscale_cp0_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	u32 cp_access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	/* do not attempt to probe iwmmxt on non-xscale family CPUs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (!cpu_is_xscale_family())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	cp_access = xscale_cp_access_read() & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	xscale_cp_access_write(cp_access | 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (cpu_has_iwmmxt()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #ifndef CONFIG_IWMMXT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		pr_warn("CAUTION: XScale iWMMXt coprocessor detected, but kernel support is missing.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		pr_info("XScale iWMMXt coprocessor detected.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		elf_hwcap |= HWCAP_IWMMXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		thread_register_notifier(&iwmmxt_notifier_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		pr_info("XScale DSP coprocessor detected.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		thread_register_notifier(&dsp_notifier_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		cp_access |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	xscale_cp_access_write(cp_access);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) late_initcall(xscale_cp0_init);