18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * OMAP SRAM detection and management
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2005 Nokia Corporation
78c2ecf20Sopenharmony_ci * Written by Tony Lindgren <tony@atomide.com>
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (C) 2009-2012 Texas Instruments
108c2ecf20Sopenharmony_ci * Added OMAP4/5 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/kernel.h>
158c2ecf20Sopenharmony_ci#include <linux/init.h>
168c2ecf20Sopenharmony_ci#include <linux/io.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <asm/fncpy.h>
198c2ecf20Sopenharmony_ci#include <asm/tlb.h>
208c2ecf20Sopenharmony_ci#include <asm/cacheflush.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <asm/mach/map.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "soc.h"
258c2ecf20Sopenharmony_ci#include "iomap.h"
268c2ecf20Sopenharmony_ci#include "prm2xxx_3xxx.h"
278c2ecf20Sopenharmony_ci#include "sdrc.h"
288c2ecf20Sopenharmony_ci#include "sram.h"
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)
318c2ecf20Sopenharmony_ci#define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define SRAM_BOOTLOADER_SZ	0x00
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define OMAP24XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68005048)
368c2ecf20Sopenharmony_ci#define OMAP24XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68005050)
378c2ecf20Sopenharmony_ci#define OMAP24XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68005058)
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define OMAP34XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68012848)
408c2ecf20Sopenharmony_ci#define OMAP34XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68012850)
418c2ecf20Sopenharmony_ci#define OMAP34XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68012858)
428c2ecf20Sopenharmony_ci#define OMAP34XX_VA_ADDR_MATCH2		OMAP2_L3_IO_ADDRESS(0x68012880)
438c2ecf20Sopenharmony_ci#define OMAP34XX_VA_SMS_RG_ATT0		OMAP2_L3_IO_ADDRESS(0x6C000048)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define GP_DEVICE		0x300
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic unsigned long omap_sram_start;
508c2ecf20Sopenharmony_cistatic unsigned long omap_sram_skip;
518c2ecf20Sopenharmony_cistatic unsigned long omap_sram_size;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/*
548c2ecf20Sopenharmony_ci * Depending on the target RAMFS firewall setup, the public usable amount of
558c2ecf20Sopenharmony_ci * SRAM varies.  The default accessible size for all device types is 2k. A GP
568c2ecf20Sopenharmony_ci * device allows ARM11 but not other initiators for full size. This
578c2ecf20Sopenharmony_ci * functionality seems ok until some nice security API happens.
588c2ecf20Sopenharmony_ci */
598c2ecf20Sopenharmony_cistatic int is_sram_locked(void)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
628c2ecf20Sopenharmony_ci		/* RAMFW: R/W access to all initiators for all qualifier sets */
638c2ecf20Sopenharmony_ci		if (cpu_is_omap242x()) {
648c2ecf20Sopenharmony_ci			writel_relaxed(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
658c2ecf20Sopenharmony_ci			writel_relaxed(0xCFDE, OMAP24XX_VA_READPERM0);  /* all i-read */
668c2ecf20Sopenharmony_ci			writel_relaxed(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */
678c2ecf20Sopenharmony_ci		}
688c2ecf20Sopenharmony_ci		if (cpu_is_omap34xx()) {
698c2ecf20Sopenharmony_ci			writel_relaxed(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */
708c2ecf20Sopenharmony_ci			writel_relaxed(0xFFFF, OMAP34XX_VA_READPERM0);  /* all i-read */
718c2ecf20Sopenharmony_ci			writel_relaxed(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */
728c2ecf20Sopenharmony_ci			writel_relaxed(0x0, OMAP34XX_VA_ADDR_MATCH2);
738c2ecf20Sopenharmony_ci			writel_relaxed(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0);
748c2ecf20Sopenharmony_ci		}
758c2ecf20Sopenharmony_ci		return 0;
768c2ecf20Sopenharmony_ci	} else
778c2ecf20Sopenharmony_ci		return 1; /* assume locked with no PPA or security driver */
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/*
818c2ecf20Sopenharmony_ci * The amount of SRAM depends on the core type.
828c2ecf20Sopenharmony_ci * Note that we cannot try to test for SRAM here because writes
838c2ecf20Sopenharmony_ci * to secure SRAM will hang the system. Also the SRAM is not
848c2ecf20Sopenharmony_ci * yet mapped at this point.
858c2ecf20Sopenharmony_ci */
868c2ecf20Sopenharmony_cistatic void __init omap_detect_sram(void)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	omap_sram_skip = SRAM_BOOTLOADER_SZ;
898c2ecf20Sopenharmony_ci	if (is_sram_locked()) {
908c2ecf20Sopenharmony_ci		if (cpu_is_omap34xx()) {
918c2ecf20Sopenharmony_ci			omap_sram_start = OMAP3_SRAM_PUB_PA;
928c2ecf20Sopenharmony_ci			if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
938c2ecf20Sopenharmony_ci			    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
948c2ecf20Sopenharmony_ci				omap_sram_size = 0x7000; /* 28K */
958c2ecf20Sopenharmony_ci				omap_sram_skip += SZ_16K;
968c2ecf20Sopenharmony_ci			} else {
978c2ecf20Sopenharmony_ci				omap_sram_size = 0x8000; /* 32K */
988c2ecf20Sopenharmony_ci			}
998c2ecf20Sopenharmony_ci		} else {
1008c2ecf20Sopenharmony_ci			omap_sram_start = OMAP2_SRAM_PUB_PA;
1018c2ecf20Sopenharmony_ci			omap_sram_size = 0x800; /* 2K */
1028c2ecf20Sopenharmony_ci		}
1038c2ecf20Sopenharmony_ci	} else {
1048c2ecf20Sopenharmony_ci		if (cpu_is_omap34xx()) {
1058c2ecf20Sopenharmony_ci			omap_sram_start = OMAP3_SRAM_PA;
1068c2ecf20Sopenharmony_ci			omap_sram_size = 0x10000; /* 64K */
1078c2ecf20Sopenharmony_ci		} else {
1088c2ecf20Sopenharmony_ci			omap_sram_start = OMAP2_SRAM_PA;
1098c2ecf20Sopenharmony_ci			if (cpu_is_omap242x())
1108c2ecf20Sopenharmony_ci				omap_sram_size = 0xa0000; /* 640K */
1118c2ecf20Sopenharmony_ci			else if (cpu_is_omap243x())
1128c2ecf20Sopenharmony_ci				omap_sram_size = 0x10000; /* 64K */
1138c2ecf20Sopenharmony_ci		}
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/*
1188c2ecf20Sopenharmony_ci * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
1198c2ecf20Sopenharmony_ci */
1208c2ecf20Sopenharmony_cistatic void __init omap2_map_sram(void)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	int cached = 1;
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	if (cpu_is_omap34xx()) {
1258c2ecf20Sopenharmony_ci		/*
1268c2ecf20Sopenharmony_ci		 * SRAM must be marked as non-cached on OMAP3 since the
1278c2ecf20Sopenharmony_ci		 * CORE DPLL M2 divider change code (in SRAM) runs with the
1288c2ecf20Sopenharmony_ci		 * SDRAM controller disabled, and if it is marked cached,
1298c2ecf20Sopenharmony_ci		 * the ARM may attempt to write cache lines back to SDRAM
1308c2ecf20Sopenharmony_ci		 * which will cause the system to hang.
1318c2ecf20Sopenharmony_ci		 */
1328c2ecf20Sopenharmony_ci		cached = 0;
1338c2ecf20Sopenharmony_ci	}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	omap_map_sram(omap_sram_start, omap_sram_size,
1368c2ecf20Sopenharmony_ci			omap_sram_skip, cached);
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
1408c2ecf20Sopenharmony_ci			      u32 base_cs, u32 force_unlock);
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_civoid omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
1438c2ecf20Sopenharmony_ci		   u32 base_cs, u32 force_unlock)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	BUG_ON(!_omap2_sram_ddr_init);
1468c2ecf20Sopenharmony_ci	_omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
1478c2ecf20Sopenharmony_ci			     base_cs, force_unlock);
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val,
1518c2ecf20Sopenharmony_ci					  u32 mem_type);
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_civoid omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	BUG_ON(!_omap2_sram_reprogram_sdrc);
1568c2ecf20Sopenharmony_ci	_omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
1578c2ecf20Sopenharmony_ci}
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ciu32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	BUG_ON(!_omap2_set_prcm);
1648c2ecf20Sopenharmony_ci	return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass);
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#ifdef CONFIG_SOC_OMAP2420
1688c2ecf20Sopenharmony_cistatic int __init omap242x_sram_init(void)
1698c2ecf20Sopenharmony_ci{
1708c2ecf20Sopenharmony_ci	_omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
1718c2ecf20Sopenharmony_ci					omap242x_sram_ddr_init_sz);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	_omap2_sram_reprogram_sdrc = omap_sram_push(omap242x_sram_reprogram_sdrc,
1748c2ecf20Sopenharmony_ci					    omap242x_sram_reprogram_sdrc_sz);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	_omap2_set_prcm = omap_sram_push(omap242x_sram_set_prcm,
1778c2ecf20Sopenharmony_ci					 omap242x_sram_set_prcm_sz);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	return 0;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci#else
1828c2ecf20Sopenharmony_cistatic inline int omap242x_sram_init(void)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	return 0;
1858c2ecf20Sopenharmony_ci}
1868c2ecf20Sopenharmony_ci#endif
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci#ifdef CONFIG_SOC_OMAP2430
1898c2ecf20Sopenharmony_cistatic int __init omap243x_sram_init(void)
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci	_omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
1928c2ecf20Sopenharmony_ci					omap243x_sram_ddr_init_sz);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci	_omap2_sram_reprogram_sdrc = omap_sram_push(omap243x_sram_reprogram_sdrc,
1958c2ecf20Sopenharmony_ci					    omap243x_sram_reprogram_sdrc_sz);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	_omap2_set_prcm = omap_sram_push(omap243x_sram_set_prcm,
1988c2ecf20Sopenharmony_ci					 omap243x_sram_set_prcm_sz);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	return 0;
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci#else
2038c2ecf20Sopenharmony_cistatic inline int omap243x_sram_init(void)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	return 0;
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci#endif
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci#ifdef CONFIG_ARCH_OMAP3
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_civoid omap3_sram_restore_context(void)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	omap_sram_reset();
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	omap_push_sram_idle();
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_cistatic inline int omap34xx_sram_init(void)
2198c2ecf20Sopenharmony_ci{
2208c2ecf20Sopenharmony_ci	omap3_sram_restore_context();
2218c2ecf20Sopenharmony_ci	return 0;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci#else
2248c2ecf20Sopenharmony_cistatic inline int omap34xx_sram_init(void)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	return 0;
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci#endif /* CONFIG_ARCH_OMAP3 */
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ciint __init omap_sram_init(void)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	omap_detect_sram();
2338c2ecf20Sopenharmony_ci	omap2_map_sram();
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (cpu_is_omap242x())
2368c2ecf20Sopenharmony_ci		omap242x_sram_init();
2378c2ecf20Sopenharmony_ci	else if (cpu_is_omap2430())
2388c2ecf20Sopenharmony_ci		omap243x_sram_init();
2398c2ecf20Sopenharmony_ci	else if (cpu_is_omap34xx())
2408c2ecf20Sopenharmony_ci		omap34xx_sram_init();
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	return 0;
2438c2ecf20Sopenharmony_ci}
244