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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  2) /* Tests for presence or absence of hardware registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  3)  * This code was originally in atari/config.c, but I noticed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  4)  * that it was also in drivers/nubus/nubus.c and I wanted to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  5)  * use it in hp300/config.c, so it seemed sensible to pull it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  6)  * out into its own file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  8)  * The test is for use when trying to read a hardware register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  9)  * that isn't present would cause a bus error. We set up a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)  * temporary handler so that this doesn't kill the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)  * There is a test-by-reading and a test-by-writing; I present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)  * them here complete with the comments from the original atari
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)  * config.c...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)  *                -- PMM <pmaydell@chiark.greenend.org.uk>, 05/1998
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* This function tests for the presence of an address, specially a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)  * hardware register address. It is called very early in the kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)  * initialization process, when the VBR register isn't set up yet. On
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)  * an Atari, it still points to address 0, which is unmapped. So a bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)  * error would cause another bus error while fetching the exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)  * vector, and the CPU would do nothing at all. So we needed to set up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)  * a temporary VBR and a vector table for the duration of the test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int hwreg_present(volatile void *regp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) 	long save_sp, save_vbr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 	long tmp_vectors[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) 	local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) 		"movec %/vbr,%2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) 		"movel #Lberr1,%4@(8)\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) 		"movec %4,%/vbr\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) 		"movel %/sp,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) 		"moveq #0,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) 		"tstb %3@\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 		"nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) 		"moveq #1,%0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 	"Lberr1:\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 		"movel %1,%/sp\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 		"movec %2,%/vbr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 		: "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 		: "a" (regp), "a" (tmp_vectors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) 	);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 	local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) EXPORT_SYMBOL(hwreg_present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Basically the same, but writes a value into a word register, protected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)  * by a bus error handler. Returns 1 if successful, 0 otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int hwreg_write(volatile void *regp, unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 	long save_sp, save_vbr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 	long tmp_vectors[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 	local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 		"movec %/vbr,%2\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 		"movel #Lberr2,%4@(8)\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 		"movec %4,%/vbr\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 		"movel %/sp,%1\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) 		"moveq #0,%0\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) 		"movew %5,%3@\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) 		"nop\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 		 * If this nop isn't present, 'ret' may already be loaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 		 * with 1 at the time the bus error happens!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) 		"moveq #1,%0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) 	"Lberr2:\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) 		"movel %1,%/sp\n\t"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 		"movec %2,%/vbr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 		: "=&d" (ret), "=&r" (save_sp), "=&r" (save_vbr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) 		: "a" (regp), "a" (tmp_vectors), "g" (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 	);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 	local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) EXPORT_SYMBOL(hwreg_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)