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