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) /* leon_pmc.c: LEON Power-down cpu_idle() handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  4)  * Copyright (C) 2011 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  7) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  8) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/leon_amba.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/cpu_type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/leon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /* List of Systems that need fixup instructions around power-down instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static unsigned int pmc_leon_fixup_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) 	AEROFLEX_UT699,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 	GAISLER_GR712RC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) 	LEON4_NEXTREME1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) 	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static int pmc_leon_need_fixup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) 	unsigned int systemid = amba_system_id >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) 	unsigned int *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) 	id = &pmc_leon_fixup_ids[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) 	while (*id != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) 		if (*id == systemid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 		id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)  * CPU idle callback function for systems that need some extra handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)  * See .../arch/sparc/kernel/process.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void pmc_leon_idle_fixup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 	/* Prepare an address to a non-cachable region. APB is always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) 	 * none-cachable. One instruction is executed after the Sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 	 * instruction, we make sure to read the bus and throw away the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 	 * value by accessing a non-cachable area, also we make sure the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 	 * MMU does not get a TLB miss here by using the MMU BYPASS ASI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 	register unsigned int address = (unsigned int)leon3_irqctrl_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 	/* Interrupts need to be enabled to not hang the CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 	raw_local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) 	__asm__ __volatile__ (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 		"wr	%%g0, %%asr19\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 		"lda	[%0] %1, %%g0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 		:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) 		: "r"(address), "i"(ASI_LEON_BYPASS));
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)  * CPU idle callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)  * See .../arch/sparc/kernel/process.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static void pmc_leon_idle(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 	/* Interrupts need to be enabled to not hang the CPU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 	raw_local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 	/* For systems without power-down, this will be no-op */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 	__asm__ __volatile__ ("wr	%g0, %asr19\n\t");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* Install LEON Power Down function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static int __init leon_pmc_install(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) 	if (sparc_cpu_model == sparc_leon) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 		/* Assign power management IDLE handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 		if (pmc_leon_need_fixup())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 			sparc_idle = pmc_leon_idle_fixup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) 			sparc_idle = pmc_leon_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 		printk(KERN_INFO "leon: power management initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* This driver is not critical to the boot process, don't care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)  * if initialized late.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) late_initcall(leon_pmc_install);