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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * ip30-smp.c: SMP on IP30 architecture.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Based off of the original IP30 SMP code, with inspiration from ip27-smp.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * and smp-bmips.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright (C) 2005-2007 Stanislaw Skowronek <skylark@unaligned.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *               2006-2007, 2014-2015 Joshua Kinard <kumba@gentoo.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *               2009 Johannes Dickgreber <tanzy@gmx.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^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/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <asm/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/sgi/heart.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "ip30-common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define MPCONF_MAGIC	0xbaddeed2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define	MPCONF_ADDR	0xa800000000000600L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define MPCONF_SIZE	0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define MPCONF(x)	(MPCONF_ADDR + (x) * MPCONF_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) /* HEART can theoretically do 4 CPUs, but only 2 are physically possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define MP_NCPU		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) struct mpconf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	u32 magic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	u32 prid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	u32 physid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	u32 virtid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	u32 scachesz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	u16 fanloads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	u16 res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	void *launch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	void *rendezvous;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	u64 res2[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	void *stackaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	void *lnch_parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	void *rndv_parm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	u32 idleflag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static void ip30_smp_send_ipi_single(int cpu, u32 action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	switch (action) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	case SMP_RESCHEDULE_YOURSELF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		irq = HEART_L2_INT_RESCHED_CPU_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	case SMP_CALL_FUNCTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		irq = HEART_L2_INT_CALL_CPU_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		panic("IP30: Unknown action value in %s!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	irq += cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	/* Poke the other CPU -- it's got mail! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	heart_write(BIT_ULL(irq), &heart_regs->set_isr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static void ip30_smp_send_ipi_mask(const struct cpumask *mask, u32 action)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	for_each_cpu(i, mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		ip30_smp_send_ipi_single(i, action);
^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) static void __init ip30_smp_setup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	int ncpu = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	struct mpconf *mpc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	init_cpu_possible(cpumask_of(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	/* Scan the MPCONF structure and enumerate available CPUs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	for (i = 0; i < MP_NCPU; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		mpc = (struct mpconf *)MPCONF(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		if (mpc->magic == MPCONF_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 			set_cpu_possible(i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			__cpu_number_map[i] = ++ncpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 			__cpu_logical_map[ncpu] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			pr_info("IP30: Slot: %d, PrID: %.8x, PhyID: %d, VirtID: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 				i, mpc->prid, mpc->physid, mpc->virtid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	pr_info("IP30: Detected %d CPU(s) present.\n", ncpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	 * Set the coherency algorithm to '5' (cacheable coherent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	 * exclusive on write).  This is needed on IP30 SMP, especially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 * for R14000 CPUs, otherwise, instruction bus errors will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	 * occur upon reaching userland.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	change_c0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_COW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static void __init ip30_smp_prepare_cpus(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	/* nothing to do here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int __init ip30_smp_boot_secondary(int cpu, struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	struct mpconf *mpc = (struct mpconf *)MPCONF(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	/* Stack pointer (sp). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	mpc->stackaddr = (void *)__KSTK_TOS(idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	/* Global pointer (gp). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	mpc->lnch_parm = task_thread_info(idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	mb(); /* make sure stack and lparm are written */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	/* Boot CPUx. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	mpc->launch = smp_bootstrap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	/* CPUx now executes smp_bootstrap, then ip30_smp_finish */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static void __init ip30_smp_init_cpu(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	ip30_per_cpu_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void __init ip30_smp_finish(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	enable_percpu_irq(get_c0_compare_int(), IRQ_TYPE_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct plat_smp_ops __read_mostly ip30_smp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	.send_ipi_single	= ip30_smp_send_ipi_single,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	.send_ipi_mask		= ip30_smp_send_ipi_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	.smp_setup		= ip30_smp_setup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	.prepare_cpus		= ip30_smp_prepare_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	.boot_secondary		= ip30_smp_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	.init_secondary		= ip30_smp_init_cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	.smp_finish		= ip30_smp_finish,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	.prepare_boot_cpu	= ip30_smp_init_cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) };