2006-04-02 20:46:20 +04:00
/*
* linux / arch / arm / mach - omap2 / prcm . c
*
* OMAP 24 xx Power Reset and Clock Management ( PRCM ) functions
*
* Copyright ( C ) 2005 Nokia Corporation
*
* Written by Tony Lindgren < tony . lindgren @ nokia . com >
*
2008-09-26 16:18:31 +04:00
* Copyright ( C ) 2007 Texas Instruments , Inc .
* Rajendra Nayak < rnayak @ ti . com >
*
2006-04-02 20:46:20 +04:00
* Some pieces of code Copyright ( C ) 2005 Texas Instruments , Inc .
2010-01-27 06:12:51 +03:00
* Upgraded with OMAP4 support by Abhijit Pagare < abhijitpagare @ ti . com >
2006-04-02 20:46:20 +04:00
*
* 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 .
*/
2010-12-22 07:05:14 +03:00
# include <linux/kernel.h>
2006-04-02 20:46:20 +04:00
# include <linux/init.h>
# include <linux/clk.h>
2008-07-03 13:24:44 +04:00
# include <linux/io.h>
2009-07-25 05:44:03 +04:00
# include <linux/delay.h>
2006-04-02 20:46:20 +04:00
2011-01-28 03:39:45 +03:00
# include <mach/system.h>
2009-10-20 20:40:47 +04:00
# include <plat/common.h>
# include <plat/prcm.h>
2008-09-26 16:18:31 +04:00
# include <plat/irqs.h>
2008-03-18 11:04:51 +03:00
2008-07-03 13:24:44 +04:00
# include "clock.h"
2010-01-27 06:13:11 +03:00
# include "clock2xxx.h"
2010-12-22 01:30:55 +03:00
# include "cm2xxx_3xxx.h"
# include "prm2xxx_3xxx.h"
2010-12-22 01:30:54 +03:00
# include "prm44xx.h"
2010-12-22 07:05:14 +03:00
# include "prminst44xx.h"
2008-03-18 11:04:51 +03:00
# include "prm-regbits-24xx.h"
2010-09-21 20:34:09 +04:00
# include "prm-regbits-44xx.h"
2010-10-08 21:40:20 +04:00
# include "control.h"
2006-04-02 20:46:20 +04:00
2010-12-22 01:30:55 +03:00
void __iomem * prm_base ;
void __iomem * cm_base ;
void __iomem * cm2_base ;
2008-07-03 13:24:44 +04:00
2009-07-25 05:44:03 +04:00
# define MAX_MODULE_ENABLE_WAIT 100000
2006-04-02 20:46:20 +04:00
u32 omap_prcm_get_reset_sources ( void )
{
2008-07-03 13:24:44 +04:00
/* XXX This presumably needs modification for 34XX */
2010-03-31 14:16:30 +04:00
if ( cpu_is_omap24xx ( ) | | cpu_is_omap34xx ( ) )
2010-12-22 07:05:14 +03:00
return omap2_prm_read_mod_reg ( WKUP_MOD , OMAP2_RM_RSTST ) & 0x7f ;
2010-01-27 06:12:51 +03:00
if ( cpu_is_omap44xx ( ) )
2010-12-22 07:05:14 +03:00
return omap2_prm_read_mod_reg ( WKUP_MOD , OMAP4_RM_RSTST ) & 0x7f ;
2010-02-24 22:05:56 +03:00
return 0 ;
2006-04-02 20:46:20 +04:00
}
EXPORT_SYMBOL ( omap_prcm_get_reset_sources ) ;
/* Resets clock rates and reboots the system. Only called from system.h */
2011-01-28 03:39:45 +03:00
static void omap_prcm_arch_reset ( char mode , const char * cmd )
2006-04-02 20:46:20 +04:00
{
2010-02-24 22:05:56 +03:00
s16 prcm_offs = 0 ;
2008-03-18 11:04:51 +03:00
2010-01-27 06:13:11 +03:00
if ( cpu_is_omap24xx ( ) ) {
omap2xxx_clk_prepare_for_reboot ( ) ;
2008-07-03 13:24:44 +04:00
prcm_offs = WKUP_MOD ;
2010-01-27 06:13:11 +03:00
} else if ( cpu_is_omap34xx ( ) ) {
2008-07-03 13:24:44 +04:00
prcm_offs = OMAP3430_GR_MOD ;
2010-12-22 06:01:21 +03:00
omap3_ctrl_write_boot_mode ( ( cmd ? ( u8 ) * cmd : 0 ) ) ;
2010-12-22 07:05:14 +03:00
} else if ( cpu_is_omap44xx ( ) ) {
omap4_prm_global_warm_sw_reset ( ) ; /* never returns */
} else {
2008-07-03 13:24:44 +04:00
WARN_ON ( 1 ) ;
2010-12-22 07:05:14 +03:00
}
2008-07-03 13:24:44 +04:00
2010-10-05 18:05:34 +04:00
/*
* As per Errata i520 , in some cases , user will not be able to
* access DDR memory after warm - reset .
* This situation occurs while the warm - reset happens during a read
* access to DDR memory . In that particular condition , DDR memory
* does not respond to a corrupted read command due to the warm
* reset occurrence but SDRC is waiting for read completion .
* SDRC is not sensitive to the warm reset , but the interconnect is
* reset on the fly , thus causing a misalignment between SDRC logic ,
* interconnect logic and DDR memory state .
* WORKAROUND :
* Steps to perform before a Warm reset is trigged :
* 1. enable self - refresh on idle request
* 2. put SDRC in idle
* 3. wait until SDRC goes to idle
* 4. generate SW reset ( Global SW reset )
*
* Steps to be performed after warm reset occurs ( in bootloader ) :
* if HW warm reset is the source , apply below steps before any
* accesses to SDRAM :
* 1. Reset SMS and SDRC and wait till reset is complete
* 2. Re - initialize SMS , SDRC and memory
*
* NOTE : Above work around is required only if arch reset is implemented
* using Global SW reset ( GLOBAL_SW_RST ) . DPLL3 reset does not need
* the WA since it resets SDRC as well as part of cold reset .
*/
2010-12-22 07:05:14 +03:00
/* XXX should be moved to some OMAP2/3 specific code */
2010-12-22 07:05:14 +03:00
omap2_prm_set_mod_reg_bits ( OMAP_RST_DPLL3_MASK , prcm_offs ,
OMAP2_RM_RSTCTRL ) ;
omap2_prm_read_mod_reg ( prcm_offs , OMAP2_RM_RSTCTRL ) ; /* OCP barrier */
2006-04-02 20:46:20 +04:00
}
2008-07-03 13:24:44 +04:00
2011-01-28 03:39:45 +03:00
void ( * arch_reset ) ( char , const char * ) = omap_prcm_arch_reset ;
2009-07-25 05:44:03 +04:00
/**
* omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness
* @ reg : physical address of module IDLEST register
* @ mask : value to mask against to determine if the module is active
2010-02-24 22:05:54 +03:00
* @ idlest : idle state indicator ( 0 or 1 ) for the clock
2009-07-25 05:44:03 +04:00
* @ name : name of the clock ( for printk )
*
* Returns 1 if the module indicated readiness in time , or 0 if it
* failed to enable in roughly MAX_MODULE_ENABLE_WAIT microseconds .
2010-12-22 01:30:55 +03:00
*
* XXX This function is deprecated . It should be removed once the
* hwmod conversion is complete .
2009-07-25 05:44:03 +04:00
*/
2010-02-24 22:05:54 +03:00
int omap2_cm_wait_idlest ( void __iomem * reg , u32 mask , u8 idlest ,
const char * name )
2009-07-25 05:44:03 +04:00
{
int i = 0 ;
int ena = 0 ;
2010-02-24 22:05:54 +03:00
if ( idlest )
2009-07-25 05:44:03 +04:00
ena = 0 ;
else
2010-02-24 22:05:54 +03:00
ena = mask ;
2009-07-25 05:44:03 +04:00
/* Wait for lock */
2009-12-09 02:33:16 +03:00
omap_test_timeout ( ( ( __raw_readl ( reg ) & mask ) = = ena ) ,
MAX_MODULE_ENABLE_WAIT , i ) ;
2009-07-25 05:44:03 +04:00
if ( i < MAX_MODULE_ENABLE_WAIT )
pr_debug ( " cm: Module associated with clock %s ready after %d "
" loops \n " , name , i ) ;
else
pr_err ( " cm: Module associated with clock %s didn't enable in "
" %d tries \n " , name , MAX_MODULE_ENABLE_WAIT ) ;
return ( i < MAX_MODULE_ENABLE_WAIT ) ? 1 : 0 ;
} ;
2008-07-03 13:24:44 +04:00
void __init omap2_set_globals_prcm ( struct omap_globals * omap2_globals )
{
2010-02-15 15:33:37 +03:00
/* Static mapping, never released */
if ( omap2_globals - > prm ) {
prm_base = ioremap ( omap2_globals - > prm , SZ_8K ) ;
WARN_ON ( ! prm_base ) ;
}
if ( omap2_globals - > cm ) {
cm_base = ioremap ( omap2_globals - > cm , SZ_8K ) ;
WARN_ON ( ! cm_base ) ;
}
if ( omap2_globals - > cm2 ) {
cm2_base = ioremap ( omap2_globals - > cm2 , SZ_8K ) ;
WARN_ON ( ! cm2_base ) ;
}
2008-07-03 13:24:44 +04:00
}