2005-09-07 20:20:26 +04: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 >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
2008-07-03 13:24:38 +04:00
# undef DEBUG
2005-09-07 20:20:26 +04:00
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
2006-02-09 01:06:45 +03:00
# include <asm/tlb.h>
2005-09-07 20:20:26 +04:00
# include <asm/io.h>
# include <asm/cacheflush.h>
2006-04-02 20:46:25 +04:00
# include <asm/mach/map.h>
2005-11-10 17:26:50 +03:00
# include <asm/arch/sram.h>
2006-04-02 20:46:25 +04:00
# include <asm/arch/board.h>
2005-11-10 17:26:50 +03:00
2008-07-03 13:24:38 +04:00
# include <asm/arch/control.h>
# if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
# include ".. / mach-omap2 / prm.h"
# include ".. / mach-omap2 / cm.h"
# include ".. / mach-omap2 / sdrc.h"
# endif
2005-11-10 17:26:50 +03:00
# define OMAP1_SRAM_PA 0x20000000
2008-07-03 13:24:38 +04:00
# define OMAP1_SRAM_VA VMALLOC_END
2005-11-10 17:26:50 +03:00
# define OMAP2_SRAM_PA 0x40200000
2006-04-02 20:46:25 +04:00
# define OMAP2_SRAM_PUB_PA 0x4020f800
2008-07-03 13:24:38 +04:00
# define OMAP2_SRAM_VA VMALLOC_END
# define OMAP2_SRAM_PUB_VA (VMALLOC_END + 0x800)
# define OMAP3_SRAM_PA 0x40200000
# define OMAP3_SRAM_VA 0xd7000000
# define OMAP3_SRAM_PUB_PA 0x40208000
# define OMAP3_SRAM_PUB_VA 0xd7008000
# if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
2006-04-02 20:46:25 +04:00
# define SRAM_BOOTLOADER_SZ 0x00
# else
2005-09-07 20:20:26 +04:00
# define SRAM_BOOTLOADER_SZ 0x80
2006-04-02 20:46:25 +04:00
# endif
2008-07-03 13:24:38 +04:00
# define OMAP24XX_VA_REQINFOPERM0 IO_ADDRESS(0x68005048)
# define OMAP24XX_VA_READPERM0 IO_ADDRESS(0x68005050)
# define OMAP24XX_VA_WRITEPERM0 IO_ADDRESS(0x68005058)
# define OMAP34XX_VA_REQINFOPERM0 IO_ADDRESS(0x68012848)
# define OMAP34XX_VA_READPERM0 IO_ADDRESS(0x68012850)
# define OMAP34XX_VA_WRITEPERM0 IO_ADDRESS(0x68012858)
# define OMAP34XX_VA_ADDR_MATCH2 IO_ADDRESS(0x68012880)
# define OMAP34XX_VA_SMS_RG_ATT0 IO_ADDRESS(0x6C000048)
# define OMAP34XX_VA_CONTROL_STAT IO_ADDRESS(0x480022F0)
2006-04-02 20:46:25 +04:00
# define GP_DEVICE 0x300
# define ROUND_DOWN(value,boundary) ((value) & (~((boundary)-1)))
2005-09-07 20:20:26 +04:00
2006-12-08 00:58:10 +03:00
static unsigned long omap_sram_start ;
2005-09-07 20:20:26 +04:00
static unsigned long omap_sram_base ;
static unsigned long omap_sram_size ;
static unsigned long omap_sram_ceil ;
2007-03-06 14:16:36 +03:00
extern unsigned long omapfb_reserve_sram ( unsigned long sram_pstart ,
unsigned long sram_vstart ,
unsigned long sram_size ,
unsigned long pstart_avail ,
unsigned long size_avail ) ;
2006-04-02 20:46:25 +04:00
2007-03-06 14:16:36 +03:00
/*
* Depending on the target RAMFS firewall setup , the public usable amount of
2007-05-11 23:40:30 +04:00
* SRAM varies . The default accessible size for all device types is 2 k . A GP
* device allows ARM11 but not other initiators for full size . This
2006-04-02 20:46:25 +04:00
* functionality seems ok until some nice security API happens .
*/
static int is_sram_locked ( void )
{
int type = 0 ;
if ( cpu_is_omap242x ( ) )
2008-07-03 13:24:38 +04:00
type = system_rev & OMAP2_DEVICETYPE_MASK ;
2006-04-02 20:46:25 +04:00
if ( type = = GP_DEVICE ) {
2007-05-11 23:40:30 +04:00
/* RAMFW: R/W access to all initiators for all qualifier sets */
2006-04-02 20:46:25 +04:00
if ( cpu_is_omap242x ( ) ) {
2008-07-03 13:24:38 +04:00
__raw_writel ( 0xFF , OMAP24XX_VA_REQINFOPERM0 ) ; /* all q-vects */
__raw_writel ( 0xCFDE , OMAP24XX_VA_READPERM0 ) ; /* all i-read */
__raw_writel ( 0xCFDE , OMAP24XX_VA_WRITEPERM0 ) ; /* all i-write */
}
if ( cpu_is_omap34xx ( ) ) {
__raw_writel ( 0xFFFF , OMAP34XX_VA_REQINFOPERM0 ) ; /* all q-vects */
__raw_writel ( 0xFFFF , OMAP34XX_VA_READPERM0 ) ; /* all i-read */
__raw_writel ( 0xFFFF , OMAP34XX_VA_WRITEPERM0 ) ; /* all i-write */
__raw_writel ( 0x0 , OMAP34XX_VA_ADDR_MATCH2 ) ;
__raw_writel ( 0xFFFFFFFF , OMAP34XX_VA_SMS_RG_ATT0 ) ;
2006-04-02 20:46:25 +04:00
}
return 0 ;
} else
return 1 ; /* assume locked with no PPA or security driver */
}
2005-09-07 20:20:26 +04:00
/*
2005-11-10 17:26:50 +03:00
* The amount of SRAM depends on the core type .
2005-09-07 20:20:26 +04:00
* Note that we cannot try to test for SRAM here because writes
* to secure SRAM will hang the system . Also the SRAM is not
* yet mapped at this point .
*/
void __init omap_detect_sram ( void )
{
2007-03-06 14:16:36 +03:00
unsigned long reserved ;
2006-04-02 20:46:25 +04:00
2008-07-03 13:24:38 +04:00
if ( cpu_class_is_omap2 ( ) ) {
2006-04-02 20:46:25 +04:00
if ( is_sram_locked ( ) ) {
2008-07-03 13:24:38 +04:00
if ( cpu_is_omap34xx ( ) ) {
omap_sram_base = OMAP3_SRAM_PUB_VA ;
omap_sram_start = OMAP3_SRAM_PUB_PA ;
omap_sram_size = 0x8000 ; /* 32K */
} else {
omap_sram_base = OMAP2_SRAM_PUB_VA ;
omap_sram_start = OMAP2_SRAM_PUB_PA ;
omap_sram_size = 0x800 ; /* 2K */
}
2006-04-02 20:46:25 +04:00
} else {
2008-07-03 13:24:38 +04:00
if ( cpu_is_omap34xx ( ) ) {
omap_sram_base = OMAP3_SRAM_VA ;
omap_sram_start = OMAP3_SRAM_PA ;
2006-04-02 20:46:25 +04:00
omap_sram_size = 0x10000 ; /* 64K */
2008-07-03 13:24:38 +04:00
} else {
omap_sram_base = OMAP2_SRAM_VA ;
omap_sram_start = OMAP2_SRAM_PA ;
if ( cpu_is_omap242x ( ) )
omap_sram_size = 0xa0000 ; /* 640K */
else if ( cpu_is_omap243x ( ) )
omap_sram_size = 0x10000 ; /* 64K */
}
2006-04-02 20:46:25 +04:00
}
} else {
2005-11-10 17:26:50 +03:00
omap_sram_base = OMAP1_SRAM_VA ;
2006-12-08 00:58:10 +03:00
omap_sram_start = OMAP1_SRAM_PA ;
2006-04-02 20:46:25 +04:00
if ( cpu_is_omap730 ( ) )
omap_sram_size = 0x32000 ; /* 200K */
else if ( cpu_is_omap15xx ( ) )
omap_sram_size = 0x30000 ; /* 192K */
else if ( cpu_is_omap1610 ( ) | | cpu_is_omap1621 ( ) | |
cpu_is_omap1710 ( ) )
omap_sram_size = 0x4000 ; /* 16K */
else if ( cpu_is_omap1611 ( ) )
omap_sram_size = 0x3e800 ; /* 250K */
else {
printk ( KERN_ERR " Could not detect SRAM size \n " ) ;
omap_sram_size = 0x4000 ;
}
2005-09-07 20:20:26 +04:00
}
2007-03-06 14:16:36 +03:00
reserved = omapfb_reserve_sram ( omap_sram_start , omap_sram_base ,
omap_sram_size ,
omap_sram_start + SRAM_BOOTLOADER_SZ ,
omap_sram_size - SRAM_BOOTLOADER_SZ ) ;
omap_sram_size - = reserved ;
2005-09-07 20:20:26 +04:00
omap_sram_ceil = omap_sram_base + omap_sram_size ;
}
static struct map_desc omap_sram_io_desc [ ] __initdata = {
2005-10-28 18:19:00 +04:00
{ /* .length gets filled in at runtime */
2005-11-10 17:26:50 +03:00
. virtual = OMAP1_SRAM_VA ,
. pfn = __phys_to_pfn ( OMAP1_SRAM_PA ) ,
2006-06-27 03:16:24 +04:00
. type = MT_MEMORY
2005-10-28 18:19:00 +04:00
}
2005-09-07 20:20:26 +04:00
} ;
/*
2006-06-27 03:16:24 +04:00
* Note that we cannot use ioremap for SRAM , as clock init needs SRAM early .
2005-09-07 20:20:26 +04:00
*/
void __init omap_map_sram ( void )
{
2006-04-02 20:46:25 +04:00
unsigned long base ;
2005-09-07 20:20:26 +04:00
if ( omap_sram_size = = 0 )
return ;
2005-11-10 17:26:50 +03:00
if ( cpu_is_omap24xx ( ) ) {
omap_sram_io_desc [ 0 ] . virtual = OMAP2_SRAM_VA ;
2006-04-02 20:46:25 +04:00
2006-09-25 13:41:24 +04:00
base = OMAP2_SRAM_PA ;
2006-04-02 20:46:25 +04:00
base = ROUND_DOWN ( base , PAGE_SIZE ) ;
omap_sram_io_desc [ 0 ] . pfn = __phys_to_pfn ( base ) ;
2005-11-10 17:26:50 +03:00
}
2008-07-03 13:24:38 +04:00
if ( cpu_is_omap34xx ( ) ) {
omap_sram_io_desc [ 0 ] . virtual = OMAP3_SRAM_VA ;
base = OMAP3_SRAM_PA ;
base = ROUND_DOWN ( base , PAGE_SIZE ) ;
omap_sram_io_desc [ 0 ] . pfn = __phys_to_pfn ( base ) ;
}
2006-06-27 03:16:24 +04:00
omap_sram_io_desc [ 0 ] . length = 1024 * 1024 ; /* Use section desc */
2005-09-07 20:20:26 +04:00
iotable_init ( omap_sram_io_desc , ARRAY_SIZE ( omap_sram_io_desc ) ) ;
2005-11-10 17:26:50 +03:00
printk ( KERN_INFO " SRAM: Mapped pa 0x%08lx to va 0x%08lx size: 0x%lx \n " ,
2006-04-02 20:46:25 +04:00
__pfn_to_phys ( omap_sram_io_desc [ 0 ] . pfn ) ,
omap_sram_io_desc [ 0 ] . virtual ,
2005-11-10 17:26:50 +03:00
omap_sram_io_desc [ 0 ] . length ) ;
2006-02-09 01:06:45 +03:00
/*
* Normally devicemaps_init ( ) would flush caches and tlb after
* mdesc - > map_io ( ) , but since we ' re called from map_io ( ) , we
* must do it here .
*/
local_flush_tlb_all ( ) ;
flush_cache_all ( ) ;
2005-09-07 20:20:26 +04:00
/*
* Looks like we need to preserve some bootloader code at the
* beginning of SRAM for jumping to flash for reboot to work . . .
*/
memset ( ( void * ) omap_sram_base + SRAM_BOOTLOADER_SZ , 0 ,
omap_sram_size - SRAM_BOOTLOADER_SZ ) ;
}
void * omap_sram_push ( void * start , unsigned long size )
{
if ( size > ( omap_sram_ceil - ( omap_sram_base + SRAM_BOOTLOADER_SZ ) ) ) {
printk ( KERN_ERR " Not enough space in SRAM \n " ) ;
return NULL ;
}
2006-04-02 20:46:25 +04:00
2005-09-07 20:20:26 +04:00
omap_sram_ceil - = size ;
2006-04-02 20:46:25 +04:00
omap_sram_ceil = ROUND_DOWN ( omap_sram_ceil , sizeof ( void * ) ) ;
2005-09-07 20:20:26 +04:00
memcpy ( ( void * ) omap_sram_ceil , start , size ) ;
2008-07-03 13:24:38 +04:00
flush_icache_range ( ( unsigned long ) start , ( unsigned long ) ( start + size ) ) ;
2005-09-07 20:20:26 +04:00
return ( void * ) omap_sram_ceil ;
}
2005-11-10 17:26:50 +03:00
static void omap_sram_error ( void )
{
panic ( " Uninitialized SRAM function \n " ) ;
}
# ifdef CONFIG_ARCH_OMAP1
static void ( * _omap_sram_reprogram_clock ) ( u32 dpllctl , u32 ckctl ) ;
void omap_sram_reprogram_clock ( u32 dpllctl , u32 ckctl )
{
if ( ! _omap_sram_reprogram_clock )
omap_sram_error ( ) ;
return _omap_sram_reprogram_clock ( dpllctl , ckctl ) ;
}
int __init omap1_sram_init ( void )
2005-09-07 20:20:26 +04:00
{
2008-07-03 13:24:38 +04:00
_omap_sram_reprogram_clock =
omap_sram_push ( omap1_sram_reprogram_clock ,
omap1_sram_reprogram_clock_sz ) ;
2005-11-10 17:26:50 +03:00
return 0 ;
}
# else
# define omap1_sram_init() do {} while (0)
# endif
2008-07-03 13:24:38 +04:00
# if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
2005-11-10 17:26:50 +03:00
static void ( * _omap2_sram_ddr_init ) ( u32 * slow_dll_ctrl , u32 fast_dll_ctrl ,
u32 base_cs , u32 force_unlock ) ;
void omap2_sram_ddr_init ( u32 * slow_dll_ctrl , u32 fast_dll_ctrl ,
u32 base_cs , u32 force_unlock )
{
if ( ! _omap2_sram_ddr_init )
omap_sram_error ( ) ;
return _omap2_sram_ddr_init ( slow_dll_ctrl , fast_dll_ctrl ,
base_cs , force_unlock ) ;
}
static void ( * _omap2_sram_reprogram_sdrc ) ( u32 perf_level , u32 dll_val ,
u32 mem_type ) ;
void omap2_sram_reprogram_sdrc ( u32 perf_level , u32 dll_val , u32 mem_type )
{
if ( ! _omap2_sram_reprogram_sdrc )
omap_sram_error ( ) ;
return _omap2_sram_reprogram_sdrc ( perf_level , dll_val , mem_type ) ;
}
static u32 ( * _omap2_set_prcm ) ( u32 dpll_ctrl_val , u32 sdrc_rfr_val , int bypass ) ;
u32 omap2_set_prcm ( u32 dpll_ctrl_val , u32 sdrc_rfr_val , int bypass )
{
if ( ! _omap2_set_prcm )
omap_sram_error ( ) ;
return _omap2_set_prcm ( dpll_ctrl_val , sdrc_rfr_val , bypass ) ;
}
2008-07-03 13:24:38 +04:00
# endif
# ifdef CONFIG_ARCH_OMAP2420
int __init omap242x_sram_init ( void )
{
_omap2_sram_ddr_init = omap_sram_push ( omap242x_sram_ddr_init ,
omap242x_sram_ddr_init_sz ) ;
_omap2_sram_reprogram_sdrc = omap_sram_push ( omap242x_sram_reprogram_sdrc ,
omap242x_sram_reprogram_sdrc_sz ) ;
_omap2_set_prcm = omap_sram_push ( omap242x_sram_set_prcm ,
omap242x_sram_set_prcm_sz ) ;
return 0 ;
}
# else
static inline int omap242x_sram_init ( void )
{
return 0 ;
}
# endif
# ifdef CONFIG_ARCH_OMAP2430
int __init omap243x_sram_init ( void )
{
_omap2_sram_ddr_init = omap_sram_push ( omap243x_sram_ddr_init ,
omap243x_sram_ddr_init_sz ) ;
_omap2_sram_reprogram_sdrc = omap_sram_push ( omap243x_sram_reprogram_sdrc ,
omap243x_sram_reprogram_sdrc_sz ) ;
_omap2_set_prcm = omap_sram_push ( omap243x_sram_set_prcm ,
omap243x_sram_set_prcm_sz ) ;
return 0 ;
}
# else
static inline int omap243x_sram_init ( void )
{
return 0 ;
}
# endif
# ifdef CONFIG_ARCH_OMAP3
static u32 ( * _omap2_sram_reprogram_gpmc ) ( u32 perf_level ) ;
u32 omap2_sram_reprogram_gpmc ( u32 perf_level )
{
if ( ! _omap2_sram_reprogram_gpmc )
omap_sram_error ( ) ;
return _omap2_sram_reprogram_gpmc ( perf_level ) ;
}
static u32 ( * _omap2_sram_configure_core_dpll ) ( u32 m , u32 n ,
u32 freqsel , u32 m2 ) ;
u32 omap2_sram_configure_core_dpll ( u32 m , u32 n , u32 freqsel , u32 m2 )
{
if ( ! _omap2_sram_configure_core_dpll )
omap_sram_error ( ) ;
return _omap2_sram_configure_core_dpll ( m , n , freqsel , m2 ) ;
}
2005-11-10 17:26:50 +03:00
2008-07-03 13:24:38 +04:00
/* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */
void restore_sram_functions ( void )
2005-11-10 17:26:50 +03:00
{
2008-07-03 13:24:38 +04:00
omap_sram_ceil = omap_sram_base + omap_sram_size ;
2005-11-10 17:26:50 +03:00
2008-07-03 13:24:38 +04:00
_omap2_sram_reprogram_gpmc = omap_sram_push ( omap34xx_sram_reprogram_gpmc ,
omap34xx_sram_reprogram_gpmc_sz ) ;
_omap2_sram_configure_core_dpll =
omap_sram_push ( omap34xx_sram_configure_core_dpll ,
omap34xx_sram_configure_core_dpll_sz ) ;
}
int __init omap34xx_sram_init ( void )
{
_omap2_sram_ddr_init = omap_sram_push ( omap34xx_sram_ddr_init ,
omap34xx_sram_ddr_init_sz ) ;
_omap2_sram_reprogram_sdrc = omap_sram_push ( omap34xx_sram_reprogram_sdrc ,
omap34xx_sram_reprogram_sdrc_sz ) ;
_omap2_set_prcm = omap_sram_push ( omap34xx_sram_set_prcm ,
omap34xx_sram_set_prcm_sz ) ;
_omap2_sram_reprogram_gpmc = omap_sram_push ( omap34xx_sram_reprogram_gpmc ,
omap34xx_sram_reprogram_gpmc_sz ) ;
_omap2_sram_configure_core_dpll =
omap_sram_push ( omap34xx_sram_configure_core_dpll ,
omap34xx_sram_configure_core_dpll_sz ) ;
2005-11-10 17:26:50 +03:00
return 0 ;
}
# else
2008-07-03 13:24:38 +04:00
static inline int omap34xx_sram_init ( void )
{
return 0 ;
}
2005-11-10 17:26:50 +03:00
# endif
int __init omap_sram_init ( void )
{
omap_detect_sram ( ) ;
omap_map_sram ( ) ;
2008-07-03 13:24:38 +04:00
if ( ! ( cpu_class_is_omap2 ( ) ) )
2005-11-10 17:26:50 +03:00
omap1_sram_init ( ) ;
2008-07-03 13:24:38 +04:00
else if ( cpu_is_omap242x ( ) )
omap242x_sram_init ( ) ;
else if ( cpu_is_omap2430 ( ) )
omap243x_sram_init ( ) ;
else if ( cpu_is_omap34xx ( ) )
omap34xx_sram_init ( ) ;
2005-11-10 17:26:50 +03:00
return 0 ;
2005-09-07 20:20:26 +04:00
}