2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2005-09-07 17:20:26 +01:00
/*
* linux / arch / arm / plat - omap / sram . c
*
* OMAP SRAM detection and management
*
* Copyright ( C ) 2005 Nokia Corporation
* Written by Tony Lindgren < tony @ atomide . com >
*
2012-06-05 16:21:32 +05:30
* Copyright ( C ) 2009 - 2012 Texas Instruments
* Added OMAP4 / 5 support - Santosh Shilimkar < santosh . shilimkar @ ti . com >
2005-09-07 17:20:26 +01:00
*/
2008-07-03 12:24:38 +03:00
# undef DEBUG
2005-09-07 17:20:26 +01:00
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
2008-09-06 12:10:45 +01:00
# include <linux/io.h>
2005-09-07 17:20:26 +01:00
2012-10-29 13:54:06 -07:00
# include <asm/fncpy.h>
2006-02-08 22:06:45 +00:00
# include <asm/tlb.h>
2005-09-07 17:20:26 +01:00
# include <asm/cacheflush.h>
2018-03-21 08:16:29 -07:00
# include <asm/set_memory.h>
2005-09-07 17:20:26 +01:00
2006-04-02 17:46:25 +01:00
# include <asm/mach/map.h>
2012-12-28 02:09:15 -07:00
# include <plat/sram.h>
2006-04-02 17:46:25 +01:00
# define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
2005-09-07 17:20:26 +01:00
2011-10-04 13:52:57 -07:00
static void __iomem * omap_sram_base ;
2012-08-29 18:24:31 +03:00
static unsigned long omap_sram_skip ;
2005-09-07 17:20:26 +01:00
static unsigned long omap_sram_size ;
2011-10-04 13:52:57 -07:00
static void __iomem * omap_sram_ceil ;
2005-09-07 17:20:26 +01:00
2011-02-02 16:38:06 +01:00
/*
* Memory allocator for SRAM : calculates the new ceiling address
* for pushing a function using the fncpy API .
*
* Note that fncpy requires the returned address to be aligned
* to an 8 - byte boundary .
*/
2018-03-21 08:16:29 -07:00
static void * omap_sram_push_address ( unsigned long size )
2005-09-07 17:20:26 +01:00
{
2011-10-04 13:52:57 -07:00
unsigned long available , new_ceil = ( unsigned long ) omap_sram_ceil ;
2012-08-29 18:24:31 +03:00
available = omap_sram_ceil - ( omap_sram_base + omap_sram_skip ) ;
2011-10-04 13:52:57 -07:00
if ( size > available ) {
2011-04-04 14:20:08 +05:30
pr_err ( " Not enough space in SRAM \n " ) ;
2005-09-07 17:20:26 +01:00
return NULL ;
}
2006-04-02 17:46:25 +01:00
2011-10-04 13:52:57 -07:00
new_ceil - = size ;
new_ceil = ROUND_DOWN ( new_ceil , FNCPY_ALIGN ) ;
omap_sram_ceil = IOMEM ( new_ceil ) ;
2005-09-07 17:20:26 +01:00
return ( void * ) omap_sram_ceil ;
}
2018-03-21 08:16:29 -07:00
void * omap_sram_push ( void * funcp , unsigned long size )
{
void * sram ;
unsigned long base ;
int pages ;
void * dst = NULL ;
sram = omap_sram_push_address ( size ) ;
if ( ! sram )
return NULL ;
base = ( unsigned long ) sram & PAGE_MASK ;
pages = PAGE_ALIGN ( size ) / PAGE_SIZE ;
set_memory_rw ( base , pages ) ;
dst = fncpy ( sram , funcp , size ) ;
set_memory_ro ( base , pages ) ;
set_memory_x ( base , pages ) ;
return dst ;
}
2012-10-29 14:36:25 -07:00
/*
* The SRAM context is lost during off - idle and stack
* needs to be reset .
*/
void omap_sram_reset ( void )
{
omap_sram_ceil = omap_sram_base + omap_sram_size ;
}
/*
* Note that we cannot use ioremap for SRAM , as clock init needs SRAM early .
*/
void __init omap_map_sram ( unsigned long start , unsigned long size ,
unsigned long skip , int cached )
{
2018-03-21 08:16:29 -07:00
unsigned long base ;
int pages ;
2012-10-29 14:36:25 -07:00
if ( size = = 0 )
return ;
start = ROUND_DOWN ( start , PAGE_SIZE ) ;
omap_sram_size = size ;
omap_sram_skip = skip ;
omap_sram_base = __arm_ioremap_exec ( start , size , cached ) ;
if ( ! omap_sram_base ) {
pr_err ( " SRAM: Could not map \n " ) ;
return ;
}
omap_sram_reset ( ) ;
/*
* Looks like we need to preserve some bootloader code at the
* beginning of SRAM for jumping to flash for reboot to work . . .
*/
memset_io ( omap_sram_base + omap_sram_skip , 0 ,
omap_sram_size - omap_sram_skip ) ;
2018-03-21 08:16:29 -07:00
base = ( unsigned long ) omap_sram_base ;
pages = PAGE_ALIGN ( omap_sram_size ) / PAGE_SIZE ;
set_memory_ro ( base , pages ) ;
set_memory_x ( base , pages ) ;
2012-10-29 14:36:25 -07:00
}