2006-04-02 17:46:20 +01: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 17:48:31 +05:30
* Copyright ( C ) 2007 Texas Instruments , Inc .
* Rajendra Nayak < rnayak @ ti . com >
*
2006-04-02 17:46:20 +01:00
* Some pieces of code Copyright ( C ) 2005 Texas Instruments , Inc .
2010-01-26 20:12:51 -07:00
* Upgraded with OMAP4 support by Abhijit Pagare < abhijitpagare @ ti . com >
2006-04-02 17:46:20 +01: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-21 21:05:14 -07:00
# include <linux/kernel.h>
2006-04-02 17:46:20 +01:00
# include <linux/init.h>
# include <linux/clk.h>
2008-07-03 12:24:44 +03:00
# include <linux/io.h>
2009-07-24 19:44:03 -06:00
# include <linux/delay.h>
2011-07-31 16:17:29 -04:00
# include <linux/export.h>
2006-04-02 17:46:20 +01:00
2011-11-10 22:45:17 +01:00
# include "common.h"
2009-10-20 09:40:47 -07:00
# include <plat/prcm.h>
2008-09-26 17:48:31 +05:30
# include <plat/irqs.h>
2008-03-18 10:04:51 +02:00
2008-07-03 12:24:44 +03:00
# include "clock.h"
2010-01-26 20:13:11 -07:00
# include "clock2xxx.h"
2010-12-21 15:30:55 -07:00
# include "cm2xxx_3xxx.h"
# include "prm2xxx_3xxx.h"
2010-12-21 15:30:54 -07:00
# include "prm44xx.h"
2010-12-21 21:05:14 -07:00
# include "prminst44xx.h"
2008-03-18 10:04:51 +02:00
# include "prm-regbits-24xx.h"
2010-09-21 10:34:09 -06:00
# include "prm-regbits-44xx.h"
2010-10-08 11:40:20 -06:00
# include "control.h"
2006-04-02 17:46:20 +01:00
2010-12-21 15:30:55 -07:00
void __iomem * prm_base ;
void __iomem * cm_base ;
void __iomem * cm2_base ;
2008-07-03 12:24:44 +03:00
2009-07-24 19:44:03 -06:00
# define MAX_MODULE_ENABLE_WAIT 100000
2006-04-02 17:46:20 +01:00
u32 omap_prcm_get_reset_sources ( void )
{
2008-07-03 12:24:44 +03:00
/* XXX This presumably needs modification for 34XX */
2010-03-31 04:16:30 -06:00
if ( cpu_is_omap24xx ( ) | | cpu_is_omap34xx ( ) )
2010-12-21 21:05:14 -07:00
return omap2_prm_read_mod_reg ( WKUP_MOD , OMAP2_RM_RSTST ) & 0x7f ;
2010-01-26 20:12:51 -07:00
if ( cpu_is_omap44xx ( ) )
2010-12-21 21:05:14 -07:00
return omap2_prm_read_mod_reg ( WKUP_MOD , OMAP4_RM_RSTST ) & 0x7f ;
2010-02-24 12:05:56 -07:00
return 0 ;
2006-04-02 17:46:20 +01:00
}
EXPORT_SYMBOL ( omap_prcm_get_reset_sources ) ;
/* Resets clock rates and reboots the system. Only called from system.h */
2011-11-05 17:06:28 +00:00
void omap_prcm_restart ( char mode , const char * cmd )
2006-04-02 17:46:20 +01:00
{
2010-02-24 12:05:56 -07:00
s16 prcm_offs = 0 ;
2008-03-18 10:04:51 +02:00
2010-01-26 20:13:11 -07:00
if ( cpu_is_omap24xx ( ) ) {
omap2xxx_clk_prepare_for_reboot ( ) ;
2008-07-03 12:24:44 +03:00
prcm_offs = WKUP_MOD ;
2010-01-26 20:13:11 -07:00
} else if ( cpu_is_omap34xx ( ) ) {
2008-07-03 12:24:44 +03:00
prcm_offs = OMAP3430_GR_MOD ;
2010-12-21 20:01:21 -07:00
omap3_ctrl_write_boot_mode ( ( cmd ? ( u8 ) * cmd : 0 ) ) ;
2010-12-21 21:05:14 -07:00
} else if ( cpu_is_omap44xx ( ) ) {
2011-07-10 05:56:31 -06:00
omap4_prminst_global_warm_sw_reset ( ) ; /* never returns */
2010-12-21 21:05:14 -07:00
} else {
2008-07-03 12:24:44 +03:00
WARN_ON ( 1 ) ;
2010-12-21 21:05:14 -07:00
}
2008-07-03 12:24:44 +03:00
2010-10-05 19:35:34 +05:30
/*
* 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-21 21:05:14 -07:00
/* XXX should be moved to some OMAP2/3 specific code */
2010-12-21 21:05:14 -07: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 17:46:20 +01:00
}
2008-07-03 12:24:44 +03:00
2009-07-24 19:44:03 -06: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 12:05:54 -07:00
* @ idlest : idle state indicator ( 0 or 1 ) for the clock
2009-07-24 19:44:03 -06: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-21 15:30:55 -07:00
*
* XXX This function is deprecated . It should be removed once the
* hwmod conversion is complete .
2009-07-24 19:44:03 -06:00
*/
2010-02-24 12:05:54 -07:00
int omap2_cm_wait_idlest ( void __iomem * reg , u32 mask , u8 idlest ,
const char * name )
2009-07-24 19:44:03 -06:00
{
int i = 0 ;
int ena = 0 ;
2010-02-24 12:05:54 -07:00
if ( idlest )
2009-07-24 19:44:03 -06:00
ena = 0 ;
else
2010-02-24 12:05:54 -07:00
ena = mask ;
2009-07-24 19:44:03 -06:00
/* Wait for lock */
2009-12-08 16:33:16 -07:00
omap_test_timeout ( ( ( __raw_readl ( reg ) & mask ) = = ena ) ,
MAX_MODULE_ENABLE_WAIT , i ) ;
2009-07-24 19:44:03 -06: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 12:24:44 +03:00
void __init omap2_set_globals_prcm ( struct omap_globals * omap2_globals )
{
2011-10-04 18:17:41 -07:00
if ( omap2_globals - > prm )
prm_base = omap2_globals - > prm ;
if ( omap2_globals - > cm )
cm_base = omap2_globals - > cm ;
if ( omap2_globals - > cm2 )
cm2_base = omap2_globals - > cm2 ;
2008-07-03 12:24:44 +03:00
}