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)  * OMAP4 SMP source file. It contains platform specific functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * needed for the linux smp kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2009 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Author:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *      Santosh Shilimkar <santosh.shilimkar@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * Platform file needed for the OMAP4 SMP. This file is based on arm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * realview smp platform.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * * Copyright (c) 2002 ARM Limited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/irqchip/arm-gic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <asm/smp_scu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <asm/virt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include "omap-secure.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include "omap-wakeupgen.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <asm/cputype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include "soc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include "iomap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include "clockdomain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include "pm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define CPU_MASK		0xff0ffff0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define CPU_CORTEX_A9		0x410FC090
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define CPU_CORTEX_A15		0x410FC0F0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define OMAP5_CORE_COUNT	0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define AUX_CORE_BOOT0_GP_RELEASE	0x020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define AUX_CORE_BOOT0_HS_RELEASE	0x200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) struct omap_smp_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	unsigned long cpu1_rstctrl_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	void __iomem *cpu1_rstctrl_va;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	void __iomem *scu_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	void __iomem *wakeupgen_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	void *startup_addr;
^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 omap_smp_config cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static const struct omap_smp_config omap443x_cfg __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	.cpu1_rstctrl_pa = 0x4824380c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	.startup_addr = omap4_secondary_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) static const struct omap_smp_config omap446x_cfg __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	.cpu1_rstctrl_pa = 0x4824380c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	.startup_addr = omap4460_secondary_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static const struct omap_smp_config omap5_cfg __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	.cpu1_rstctrl_pa = 0x48243810,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	.startup_addr = omap5_secondary_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) void __iomem *omap4_get_scu_base(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	return cfg.scu_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #ifdef CONFIG_OMAP5_ERRATA_801819
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static void omap5_erratum_workaround_801819(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	u32 acr, revidr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	u32 acr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	/* REVIDR[3] indicates erratum fix available on silicon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	asm volatile ("mrc p15, 0, %0, c0, c0, 6" : "=r" (revidr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if (revidr & (0x1 << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 * BIT(27) - Disables streaming. All write-allocate lines allocate in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 * the L1 or L2 cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	 * BIT(25) - Disables streaming. All write-allocate lines allocate in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	 * the L1 cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	acr_mask = (0x3 << 25) | (0x3 << 27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	/* do we already have it done.. if yes, skip expensive smc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if ((acr & acr_mask) == acr_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	acr |= acr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	pr_debug("%s: ARM erratum workaround 801819 applied on CPU%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		 __func__, smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static inline void omap5_erratum_workaround_801819(void) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * Configure ACR and enable ACTLR[0] (Enable invalidates of BTB with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  * ICIALLU) to activate the workaround for secondary Core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * NOTE: it is assumed that the primary core's configuration is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * by the boot loader (kernel will detect a misconfiguration and complain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * if this is not done).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * In General Purpose(GP) devices, ACR bit settings can only be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * by ROM code in "secure world" using the smc call and there is no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * option to update the "firmware" on such devices. This also works for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  * High security(HS) devices, as a backup option in case the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)  * "update" is not done in the "security firmware".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void omap5_secondary_harden_predictor(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	u32 acr, acr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	 * ACTLR[0] (Enable invalidates of BTB with ICIALLU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	acr_mask = BIT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	/* Do we already have it done.. if yes, skip expensive smc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if ((acr & acr_mask) == acr_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	acr |= acr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	pr_debug("%s: ARM ACR setup for CVE_2017_5715 applied on CPU%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		 __func__, smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static inline void omap5_secondary_harden_predictor(void) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void omap4_secondary_init(unsigned int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	 * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	 * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	 * init and for CPU1, a secure PPA API provided. CPU0 must be ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	 * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	 * OMAP443X GP devices- SMP bit isn't accessible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	 * OMAP446X GP devices - SMP bit access is enabled on both CPUs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (soc_is_omap443x() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		omap_secure_dispatcher(OMAP4_PPA_CPU_ACTRL_SMP_INDEX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 							4, 0, 0, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	if (soc_is_omap54xx() || soc_is_dra7xx()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		 * Configure the CNTFRQ register for the secondary cpu's which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		 * indicates the frequency of the cpu local timers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		set_cntfreq();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		/* Configure ACR to disable streaming WA for 801819 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		omap5_erratum_workaround_801819();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		/* Enable ACR to allow for ICUALLU workaround */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		omap5_secondary_harden_predictor();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	static struct clockdomain *cpu1_clkdm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	static bool booted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	static struct powerdomain *cpu1_pwrdm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	 * Update the AuxCoreBoot0 with boot state for secondary core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	 * omap4_secondary_startup() routine will hold the secondary core till
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	 * the AuxCoreBoot1 register is updated with cpu state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	 * A barrier is added to ensure that write buffer is drained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	if (omap_secure_apis_support())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		omap_modify_auxcoreboot0(AUX_CORE_BOOT0_HS_RELEASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 					 0xfffffdff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		writel_relaxed(AUX_CORE_BOOT0_GP_RELEASE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 			       cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (!cpu1_clkdm && !cpu1_pwrdm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		cpu1_clkdm = clkdm_lookup("mpu1_clkdm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		cpu1_pwrdm = pwrdm_lookup("cpu1_pwrdm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	 * The SGI(Software Generated Interrupts) are not wakeup capable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	 * from low power states. This is known limitation on OMAP4 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	 * needs to be worked around by using software forced clockdomain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	 * wake-up. To wakeup CPU1, CPU0 forces the CPU1 clockdomain to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	 * software force wakeup. The clockdomain is then put back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	 * hardware supervised mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	 * More details can be found in OMAP4430 TRM - Version J
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	 * Section :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	 *	4.3.4.2 Power States of CPU0 and CPU1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	if (booted && cpu1_pwrdm && cpu1_clkdm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		 * GIC distributor control register has changed between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		 * CortexA9 r1pX and r2pX. The Control Register secure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		 * banked version is now composed of 2 bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		 * bit 0 == Secure Enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		 * bit 1 == Non-Secure Enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		 * The Non-Secure banked register has not changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		 * Because the ROM Code is based on the r1pX GIC, the CPU1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		 * The workaround must be:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		 * the GIC distributor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		 * 2) CPU1 must re-enable the GIC distributor on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		 * it's wakeup path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			gic_dist_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		 * Ensure that CPU power state is set to ON to avoid CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		 * powerdomain transition on wfi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		clkdm_deny_idle_nolock(cpu1_clkdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		pwrdm_set_next_pwrst(cpu1_pwrdm, PWRDM_POWER_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		clkdm_allow_idle_nolock(cpu1_clkdm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			while (gic_dist_disabled()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 				udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 				cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 			gic_timer_retrigger();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		dsb_sev();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		booted = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * Initialise the CPU possible map early - this describes the CPUs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  * which may be present or become present in the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void __init omap4_smp_init_cpus(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	unsigned int i = 0, ncores = 1, cpu_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	/* Use ARM cpuid check here, as SoC detection will not work so early */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	cpu_id = read_cpuid_id() & CPU_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	if (cpu_id == CPU_CORTEX_A9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		 * Currently we can't call ioremap here because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		 * SoC detection won't work until after init_early.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		cfg.scu_base =  OMAP2_L4_IO_ADDRESS(scu_a9_get_base());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		BUG_ON(!cfg.scu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		ncores = scu_get_core_count(cfg.scu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	} else if (cpu_id == CPU_CORTEX_A15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		ncores = OMAP5_CORE_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	/* sanity check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	if (ncores > nr_cpu_ids) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 			ncores, nr_cpu_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		ncores = nr_cpu_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	for (i = 0; i < ncores; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		set_cpu_possible(i, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)  * For now, just make sure the start-up address is not within the booting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)  * kernel space as that means we just overwrote whatever secondary_startup()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  * code there was.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static bool __init omap4_smp_cpu1_startup_valid(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	if ((addr >= __pa(PAGE_OFFSET)) && (addr <= __pa(__bss_start)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)  * We may need to reset CPU1 before configuring, otherwise kexec boot can end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)  * up trying to use old kernel startup address or suspend-resume will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)  * occasionally fail to bring up CPU1 on 4430 if CPU1 fails to enter deeper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)  * idle states.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	unsigned long cpu1_startup_pa, cpu1_ns_pa_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	bool needs_reset = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	u32 released;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	if (omap_secure_apis_support())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		released = omap_read_auxcoreboot0() & AUX_CORE_BOOT0_HS_RELEASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		released = readl_relaxed(cfg.wakeupgen_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 					 OMAP_AUX_CORE_BOOT_0) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 						AUX_CORE_BOOT0_GP_RELEASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	if (released) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		pr_warn("smp: CPU1 not parked?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	cpu1_startup_pa = readl_relaxed(cfg.wakeupgen_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 					OMAP_AUX_CORE_BOOT_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	/* Did the configured secondary_startup() get overwritten? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		needs_reset = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	 * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	 * deeper idle state in WFI and will wake to an invalid address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	if ((soc_is_omap44xx() || soc_is_omap54xx())) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		if (!omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			needs_reset = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		cpu1_ns_pa_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	if (!needs_reset || !c->cpu1_rstctrl_va)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	pr_info("smp: CPU1 parked within kernel, needs reset (0x%lx 0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		cpu1_startup_pa, cpu1_ns_pa_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	writel_relaxed(1, c->cpu1_rstctrl_va);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	readl_relaxed(c->cpu1_rstctrl_va);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	writel_relaxed(0, c->cpu1_rstctrl_va);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	const struct omap_smp_config *c = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	if (soc_is_omap443x())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		c = &omap443x_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	else if (soc_is_omap446x())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		c = &omap446x_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	else if (soc_is_dra74x() || soc_is_omap54xx() || soc_is_dra76x())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		c = &omap5_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	if (!c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		pr_err("%s Unknown SMP SoC?\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	/* Must preserve cfg.scu_base set earlier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	cfg.cpu1_rstctrl_pa = c->cpu1_rstctrl_pa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	cfg.startup_addr = c->startup_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	cfg.wakeupgen_base = omap_get_wakeupgen_base();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	if (soc_is_dra74x() || soc_is_omap54xx() || soc_is_dra76x()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 			cfg.startup_addr = omap5_secondary_hyp_startup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		omap5_erratum_workaround_801819();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	cfg.cpu1_rstctrl_va = ioremap(cfg.cpu1_rstctrl_pa, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	if (!cfg.cpu1_rstctrl_va)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	 * Initialise the SCU and wake up the secondary core using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	 * wakeup_secondary().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	if (cfg.scu_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		scu_enable(cfg.scu_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	omap4_smp_maybe_reset_cpu1(&cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	 * Write the address of secondary startup routine into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	 * AuxCoreBoot1 where ROM code will jump and start executing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	 * on secondary core once out of WFE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	 * A barrier is added to ensure that write buffer is drained
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	if (omap_secure_apis_support())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		omap_auxcoreboot_addr(__pa_symbol(cfg.startup_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 		writel_relaxed(__pa_symbol(cfg.startup_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 			       cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) const struct smp_operations omap4_smp_ops __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	.smp_init_cpus		= omap4_smp_init_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	.smp_prepare_cpus	= omap4_smp_prepare_cpus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	.smp_secondary_init	= omap4_secondary_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	.smp_boot_secondary	= omap4_boot_secondary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #ifdef CONFIG_HOTPLUG_CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	.cpu_die		= omap4_cpu_die,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	.cpu_kill		= omap4_cpu_kill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) };