2007-10-10 20:29:49 +04:00
/*
* arch / blackfin / kernel / reboot . c - handle shutdown / reboot
*
* Copyright 2004 - 2007 Analog Devices Inc .
*
* Licensed under the GPL - 2 or later .
*/
# include <linux/interrupt.h>
# include <asm/bfin-global.h>
# include <asm/reboot.h>
2008-10-13 07:33:43 +04:00
# include <asm/bfrom.h>
2007-10-10 20:29:49 +04:00
2008-04-23 04:01:31 +04:00
/* A system soft reset makes external memory unusable so force
* this function into L1 . We use the compiler ssync here rather
* than SSYNC ( ) because it ' s safe ( no interrupts and such ) and
* we save some L1 . We do not need to force sanity in the SYSCR
* register as the BMODE selection bit is cleared by the soft
* reset while the Core B bit ( on dual core parts ) is cleared by
* the core reset .
2007-10-10 20:29:49 +04:00
*/
2009-02-04 11:49:45 +03:00
__attribute__ ( ( __l1_text__ , __noreturn__ ) )
2009-02-04 11:49:45 +03:00
static void bfin_reset ( void )
2007-10-10 20:29:49 +04:00
{
2012-05-16 13:37:24 +04:00
# ifndef CONFIG_BF60x
2011-05-02 08:00:35 +04:00
if ( ! ANOMALY_05000353 & & ! ANOMALY_05000386 )
bfrom_SoftReset ( ( void * ) ( L1_SCRATCH_START + L1_SCRATCH_LENGTH - 20 ) ) ;
2008-04-23 04:01:31 +04:00
/* Wait for completion of "system" events such as cache line
* line fills so that we avoid infinite stalls later on as
* much as possible . This code is in L1 , so it won ' t trigger
* any such event after this point in time .
*/
__builtin_bfin_ssync ( ) ;
2007-10-10 20:29:49 +04:00
2011-05-02 08:00:35 +04:00
/* Initiate System software reset. */
bfin_write_SWRST ( 0x7 ) ;
2008-01-22 13:38:02 +03:00
2011-05-02 08:00:35 +04:00
/* Due to the way reset is handled in the hardware, we need
* to delay for 10 SCLKS . The only reliable way to do this is
* to calculate the CCLK / SCLK ratio and multiply 10. For now ,
* we ' ll assume worse case which is a 1 : 15 ratio .
*/
asm (
" LSETUP (1f, 1f) LC0 = %0 \n "
" 1: nop; "
:
: " a " ( 15 * 10 )
: " LC0 " , " LB0 " , " LT0 "
) ;
2008-01-22 13:38:02 +03:00
2011-05-02 08:00:35 +04:00
/* Clear System software reset */
bfin_write_SWRST ( 0 ) ;
2008-04-23 04:01:31 +04:00
2011-05-02 08:00:35 +04:00
/* The BF526 ROM will crash during reset */
2009-02-04 11:49:45 +03:00
# if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__)
2011-06-30 08:49:30 +04:00
/* Seems to be fixed with newer parts though ... */
if ( __SILICON_REVISION__ < 1 & & bfin_revid ( ) < 1 )
bfin_read_SWRST ( ) ;
2009-02-04 11:49:45 +03:00
# endif
2011-05-02 08:00:35 +04:00
/* Wait for the SWRST write to complete. Cannot rely on SSYNC
* though as the System state is all reset now .
*/
asm (
" LSETUP (1f, 1f) LC1 = %0 \n "
" 1: nop; "
:
: " a " ( 15 * 1 )
: " LC1 " , " LB1 " , " LT1 "
) ;
2008-04-23 04:01:31 +04:00
2009-02-04 11:49:45 +03:00
while ( 1 )
2008-04-23 04:01:31 +04:00
/* Issue core reset */
2007-10-10 20:29:49 +04:00
asm ( " raise 1 " ) ;
2012-05-16 13:37:24 +04:00
# else
while ( 1 )
bfin_write_RCU0_CTL ( 0x1 ) ;
# endif
2007-10-10 20:29:49 +04:00
}
__attribute__ ( ( weak ) )
void native_machine_restart ( char * cmd )
{
}
void machine_restart ( char * cmd )
{
native_machine_restart ( cmd ) ;
2008-11-18 12:48:22 +03:00
if ( smp_processor_id ( ) )
smp_call_function ( ( void * ) bfin_reset , 0 , 1 ) ;
2008-10-13 07:33:43 +04:00
else
2008-11-18 12:48:22 +03:00
bfin_reset ( ) ;
2007-10-10 20:29:49 +04:00
}
__attribute__ ( ( weak ) )
void native_machine_halt ( void )
{
idle_with_irq_disabled ( ) ;
}
void machine_halt ( void )
{
native_machine_halt ( ) ;
}
__attribute__ ( ( weak ) )
void native_machine_power_off ( void )
{
idle_with_irq_disabled ( ) ;
}
void machine_power_off ( void )
{
native_machine_power_off ( ) ;
}