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)  * Copyright (C) 2008-2009 ST-Ericsson AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * TCM memory handling for ARM systems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Author: Linus Walleij <linus.walleij@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Author: Rickard Andersson <rickard.andersson@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/genalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/string.h> /* memcpy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <asm/cputype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/mach/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <asm/memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <asm/system_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <asm/tcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define TCMTR_FORMAT_MASK	0xe0000000U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static struct gen_pool *tcm_pool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static bool dtcm_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static bool itcm_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) /* TCM section definitions from the linker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) extern char __itcm_start, __sitcm_text, __eitcm_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) extern char __dtcm_start, __sdtcm_data, __edtcm_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) /* These will be increased as we run */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static u32 dtcm_end = DTCM_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static u32 itcm_end = ITCM_OFFSET;
^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)  * TCM memory resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static struct resource dtcm_res = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	.name = "DTCM RAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	.start = DTCM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	.end = DTCM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	.flags = IORESOURCE_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static struct resource itcm_res = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	.name = "ITCM RAM",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	.start = ITCM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	.end = ITCM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	.flags = IORESOURCE_MEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static struct map_desc dtcm_iomap[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		.virtual	= DTCM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		.pfn		= __phys_to_pfn(DTCM_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		.length		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		.type		= MT_MEMORY_RW_DTCM
^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) static struct map_desc itcm_iomap[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		.virtual	= ITCM_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		.pfn		= __phys_to_pfn(ITCM_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		.length		= 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		.type		= MT_MEMORY_RWX_ITCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	}
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * Allocate a chunk of TCM memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) void *tcm_alloc(size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	unsigned long vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (!tcm_pool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	vaddr = gen_pool_alloc(tcm_pool, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	if (!vaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	return (void *) vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) EXPORT_SYMBOL(tcm_alloc);
^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)  * Free a chunk of TCM memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) void tcm_free(void *addr, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	gen_pool_free(tcm_pool, (unsigned long) addr, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) EXPORT_SYMBOL(tcm_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) bool tcm_dtcm_present(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return dtcm_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) EXPORT_SYMBOL(tcm_dtcm_present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) bool tcm_itcm_present(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	return itcm_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) EXPORT_SYMBOL(tcm_itcm_present);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				  u32 *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 				    256, 512, 1024, -1, -1, -1, -1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	u32 tcm_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	int tcm_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	 * If there are more than one TCM bank of this type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	 * select the TCM bank to operate on in the TCM selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	 * register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	if (banks > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		asm("mcr	p15, 0, %0, c9, c2, 0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		    : /* No output operands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		    : "r" (bank));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	/* Read the special TCM region register c9, 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (!type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		asm("mrc	p15, 0, %0, c9, c1, 0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		    : "=r" (tcm_region));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		asm("mrc	p15, 0, %0, c9, c1, 1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		    : "=r" (tcm_region));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	if (tcm_size < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		pr_err("CPU: %sTCM%d of unknown size\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		       type ? "I" : "D", bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	} else if (tcm_size > 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		pr_err("CPU: %sTCM%d larger than 32k found\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		       type ? "I" : "D", bank);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		pr_info("CPU: found %sTCM%d %dk @ %08x, %senabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			type ? "I" : "D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			tcm_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			(tcm_region & 0xfffff000U),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 			(tcm_region & 1) ? "" : "not ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	/* Not much fun you can do with a size 0 bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	if (tcm_size == 0)
^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) 	/* Force move the TCM bank to where we want it, enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (!type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		asm("mcr	p15, 0, %0, c9, c1, 0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		    : /* No output operands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		    : "r" (tcm_region));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		asm("mcr	p15, 0, %0, c9, c1, 1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		    : /* No output operands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		    : "r" (tcm_region));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	/* Increase offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	*offset += (tcm_size << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	pr_info("CPU: moved %sTCM%d %dk to %08x, enabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		type ? "I" : "D",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		tcm_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		(tcm_region & 0xfffff000U));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * When we are running in the non-secure world and the secure world
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * has not explicitly given us access to the TCM we will get an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * undefined error when reading the TCM region register in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * setup_tcm_bank function (above).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  * There are two variants of this register read that we need to trap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  * the read for the data TCM and the read for the instruction TCM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  *  c0370628:       ee196f11        mrc     15, 0, r6, cr9, cr1, {0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  *  c0370674:       ee196f31        mrc     15, 0, r6, cr9, cr1, {1}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  * Our undef hook mask explicitly matches all fields of the encoded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  * instruction other than the destination register.  The mask also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  * only allows operand 2 to have the values 0 or 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * The undefined hook is defined as __init and __initdata, and therefore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  * must be removed before tcm_init returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * In this particular case (MRC with ARM condition code ALways) the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  * Thumb-2 and ARM instruction encoding are identical, so this hook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  * will work on a Thumb-2 kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  * See A8.8.107, DDI0406C_C ARM Architecture Reference Manual, Encoding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * T1/A1 for the bit-by-bit details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  *  mrc   p15, 0, XX, c9, c1, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  *  mrc   p15, 0, XX, c9, c1, 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  *   |  |  |   |   |   |   |  +---- opc2           0|1 = 000|001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  *   |  |  |   |   |   |   +------- CRm              0 = 0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  *   |  |  |   |   |   +----------- CRn              0 = 1001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  *   |  |  |   |   +--------------- Rt               ? = ????
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  *   |  |  |   +------------------- opc1             0 =  000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  *   |  |  +----------------------- coproc          15 = 1111
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  *   |  +-------------------------- condition   ALways = 1110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *   +----------------------------- instruction    MRC = 1110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * Encoding this as per A8.8.107 of DDI0406C, Encoding T1/A1, yields:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  *  1111 1111 1111 1111 0000 1111 1101 1111 Required Mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  *  1110 1110 0001 1001 ???? 1111 0001 0001 mrc p15, 0, XX, c9, c1, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  *  1110 1110 0001 1001 ???? 1111 0011 0001 mrc p15, 0, XX, c9, c1, 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  *  [  ] [  ] [ ]| [  ] [  ] [  ] [ ]| +--- CRm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  *    |    |   | |   |    |    |   | +----- SBO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  *    |    |   | |   |    |    |   +------- opc2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  *    |    |   | |   |    |    +----------- coproc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *    |    |   | |   |    +---------------- Rt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  *    |    |   | |   +--------------------- CRn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  *    |    |   | +------------------------- SBO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)  *    |    |   +--------------------------- opc1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)  *    |    +------------------------------- instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)  *    +------------------------------------ condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #define TCM_REGION_READ_MASK		0xffff0fdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #define TCM_REGION_READ_INSTR		0xee190f11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define DEST_REG_SHIFT			12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define DEST_REG_MASK			0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int __init tcm_handler(struct pt_regs *regs, unsigned int instr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	regs->uregs[(instr >> DEST_REG_SHIFT) & DEST_REG_MASK] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	regs->ARM_pc += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static struct undef_hook tcm_hook __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	.instr_mask	= TCM_REGION_READ_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	.instr_val	= TCM_REGION_READ_INSTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	.cpsr_mask	= MODE_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	.cpsr_val	= SVC_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	.fn		= tcm_handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * This initializes the TCM memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) void __init tcm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	u32 tcm_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	u8 dtcm_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	u8 itcm_banks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	size_t dtcm_code_sz = &__edtcm_data - &__sdtcm_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	size_t itcm_code_sz = &__eitcm_text - &__sitcm_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	char *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	char *ram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	 * Prior to ARMv5 there is no TCM, and trying to read the status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	 * register will hang the processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	if (cpu_architecture() < CPU_ARCH_ARMv5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		if (dtcm_code_sz || itcm_code_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 			pr_info("CPU TCM: %u bytes of DTCM and %u bytes of "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 				"ITCM code compiled in, but no TCM present "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 				"in pre-v5 CPU\n", dtcm_code_sz, itcm_code_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	tcm_status = read_cpuid_tcmstatus();
^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) 	 * This code only supports v6-compatible TCMTR implementations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (tcm_status & TCMTR_FORMAT_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	dtcm_banks = (tcm_status >> 16) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	itcm_banks = (tcm_status & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	register_undef_hook(&tcm_hook);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	/* Values greater than 2 for D/ITCM banks are "reserved" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	if (dtcm_banks > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		dtcm_banks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	if (itcm_banks > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		itcm_banks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	/* Setup DTCM if present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	if (dtcm_banks > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		for (i = 0; i < dtcm_banks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 			ret = setup_tcm_bank(0, i, dtcm_banks, &dtcm_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 				goto unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		/* This means you compiled more code than fits into DTCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		if (dtcm_code_sz > (dtcm_end - DTCM_OFFSET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 			pr_info("CPU DTCM: %u bytes of code compiled to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 				"DTCM but only %lu bytes of DTCM present\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 				dtcm_code_sz, (dtcm_end - DTCM_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			goto no_dtcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		 * This means that the DTCM sizes were 0 or the DTCM banks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		 * were inaccessible due to TrustZone configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		if (!(dtcm_end - DTCM_OFFSET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			goto no_dtcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		dtcm_res.end = dtcm_end - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		request_resource(&iomem_resource, &dtcm_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 		dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		iotable_init(dtcm_iomap, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		/* Copy data from RAM to DTCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		start = &__sdtcm_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		end   = &__edtcm_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		ram   = &__dtcm_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		memcpy(start, ram, dtcm_code_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		pr_debug("CPU DTCM: copied data from %p - %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 			 start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		dtcm_present = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	} else if (dtcm_code_sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		pr_info("CPU DTCM: %u bytes of code compiled to DTCM but no "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 			"DTCM banks present in CPU\n", dtcm_code_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) no_dtcm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	/* Setup ITCM if present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	if (itcm_banks > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		for (i = 0; i < itcm_banks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 			ret = setup_tcm_bank(1, i, itcm_banks, &itcm_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 				goto unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		/* This means you compiled more code than fits into ITCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		if (itcm_code_sz > (itcm_end - ITCM_OFFSET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			pr_info("CPU ITCM: %u bytes of code compiled to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 				"ITCM but only %lu bytes of ITCM present\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 				itcm_code_sz, (itcm_end - ITCM_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			goto unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		 * This means that the ITCM sizes were 0 or the ITCM banks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		 * were inaccessible due to TrustZone configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		if (!(itcm_end - ITCM_OFFSET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			goto unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		itcm_res.end = itcm_end - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		request_resource(&iomem_resource, &itcm_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		itcm_iomap[0].length = itcm_end - ITCM_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		iotable_init(itcm_iomap, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		/* Copy code from RAM to ITCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		start = &__sitcm_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		end   = &__eitcm_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		ram   = &__itcm_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		memcpy(start, ram, itcm_code_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		pr_debug("CPU ITCM: copied code from %p - %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			 start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		itcm_present = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	} else if (itcm_code_sz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		pr_info("CPU ITCM: %u bytes of code compiled to ITCM but no "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 			"ITCM banks present in CPU\n", itcm_code_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	unregister_undef_hook(&tcm_hook);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)  * This creates the TCM memory pool and has to be done later,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)  * during the core_initicalls, since the allocator is not yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)  * up and running when the first initialization runs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int __init setup_tcm_pool(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	u32 dtcm_pool_start = (u32) &__edtcm_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	u32 itcm_pool_start = (u32) &__eitcm_text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	 * Set up malloc pool, 2^2 = 4 bytes granularity since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	 * the TCM is sometimes just 4 KiB. NB: pages and cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	 * line alignments does not matter in TCM!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	tcm_pool = gen_pool_create(2, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	pr_debug("Setting up TCM memory pool\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	/* Add the rest of DTCM to the TCM pool */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	if (dtcm_present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		if (dtcm_pool_start < dtcm_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 			ret = gen_pool_add(tcm_pool, dtcm_pool_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 					   dtcm_end - dtcm_pool_start, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 			if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 				pr_err("CPU DTCM: could not add DTCM " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 				       "remainder to pool!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 			pr_debug("CPU DTCM: Added %08x bytes @ %08x to " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 				 "the TCM memory pool\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 				 dtcm_end - dtcm_pool_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 				 dtcm_pool_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	/* Add the rest of ITCM to the TCM pool */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	if (itcm_present) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		if (itcm_pool_start < itcm_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 			ret = gen_pool_add(tcm_pool, itcm_pool_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 					   itcm_end - itcm_pool_start, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 				pr_err("CPU ITCM: could not add ITCM " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 				       "remainder to pool!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 			pr_debug("CPU ITCM: Added %08x bytes @ %08x to " \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 				 "the TCM memory pool\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 				 itcm_end - itcm_pool_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 				 itcm_pool_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) core_initcall(setup_tcm_pool);