2019-05-28 20:10:14 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-17 02:20:36 +04:00
/*
* arch / sh / mm / cache - sh2 . c
*
* Copyright ( C ) 2002 Paul Mundt
2008-08-04 11:33:47 +04:00
* Copyright ( C ) 2008 Yoshinori Sato
2005-04-17 02:20:36 +04:00
*/
2006-11-05 09:40:13 +03:00
2005-04-17 02:20:36 +04:00
# include <linux/init.h>
# include <linux/mm.h>
# include <asm/cache.h>
# include <asm/addrspace.h>
# include <asm/processor.h>
# include <asm/cacheflush.h>
# include <asm/io.h>
2009-08-15 07:35:15 +04:00
static void sh2__flush_wback_region ( void * start , int size )
2005-04-17 02:20:36 +04:00
{
2006-11-05 09:40:13 +03:00
unsigned long v ;
unsigned long begin , end ;
begin = ( unsigned long ) start & ~ ( L1_CACHE_BYTES - 1 ) ;
end = ( ( unsigned long ) start + size + L1_CACHE_BYTES - 1 )
& ~ ( L1_CACHE_BYTES - 1 ) ;
for ( v = begin ; v < end ; v + = L1_CACHE_BYTES ) {
2008-08-04 11:33:47 +04:00
unsigned long addr = CACHE_OC_ADDRESS_ARRAY | ( v & 0x00000ff0 ) ;
int way ;
for ( way = 0 ; way < 4 ; way + + ) {
2010-01-26 06:58:40 +03:00
unsigned long data = __raw_readl ( addr | ( way < < 12 ) ) ;
2008-08-04 11:33:47 +04:00
if ( ( data & CACHE_PHYSADDR_MASK ) = = ( v & CACHE_PHYSADDR_MASK ) ) {
data & = ~ SH_CACHE_UPDATED ;
2010-01-26 06:58:40 +03:00
__raw_writel ( data , addr | ( way < < 12 ) ) ;
2008-08-04 11:33:47 +04:00
}
}
2006-11-05 09:40:13 +03:00
}
}
2009-08-15 07:35:15 +04:00
static void sh2__flush_purge_region ( void * start , int size )
2006-11-05 09:40:13 +03:00
{
unsigned long v ;
unsigned long begin , end ;
begin = ( unsigned long ) start & ~ ( L1_CACHE_BYTES - 1 ) ;
end = ( ( unsigned long ) start + size + L1_CACHE_BYTES - 1 )
& ~ ( L1_CACHE_BYTES - 1 ) ;
2008-08-04 11:33:47 +04:00
for ( v = begin ; v < end ; v + = L1_CACHE_BYTES )
2010-01-26 06:58:40 +03:00
__raw_writel ( ( v & CACHE_PHYSADDR_MASK ) ,
2008-08-04 11:33:47 +04:00
CACHE_OC_ADDRESS_ARRAY | ( v & 0x00000ff0 ) | 0x00000008 ) ;
2006-11-05 09:40:13 +03:00
}
2009-08-15 07:35:15 +04:00
static void sh2__flush_invalidate_region ( void * start , int size )
2006-11-05 09:40:13 +03:00
{
2008-08-04 11:33:47 +04:00
# ifdef CONFIG_CACHE_WRITEBACK
/*
* SH - 2 does not support individual line invalidation , only a
* global invalidate .
*/
unsigned long ccr ;
unsigned long flags ;
local_irq_save ( flags ) ;
jump_to_uncached ( ) ;
2014-03-04 03:38:33 +04:00
ccr = __raw_readl ( SH_CCR ) ;
2008-08-04 11:33:47 +04:00
ccr | = CCR_CACHE_INVALIDATE ;
2014-03-04 03:38:33 +04:00
__raw_writel ( ccr , SH_CCR ) ;
2008-08-04 11:33:47 +04:00
back_to_cached ( ) ;
local_irq_restore ( flags ) ;
# else
2006-11-05 09:40:13 +03:00
unsigned long v ;
unsigned long begin , end ;
begin = ( unsigned long ) start & ~ ( L1_CACHE_BYTES - 1 ) ;
end = ( ( unsigned long ) start + size + L1_CACHE_BYTES - 1 )
& ~ ( L1_CACHE_BYTES - 1 ) ;
2005-04-17 02:20:36 +04:00
2008-08-04 11:33:47 +04:00
for ( v = begin ; v < end ; v + = L1_CACHE_BYTES )
2010-01-26 06:58:40 +03:00
__raw_writel ( ( v & CACHE_PHYSADDR_MASK ) ,
2008-08-04 11:33:47 +04:00
CACHE_OC_ADDRESS_ARRAY | ( v & 0x00000ff0 ) | 0x00000008 ) ;
# endif
}
2009-08-15 07:35:15 +04:00
void __init sh2_cache_init ( void )
{
__flush_wback_region = sh2__flush_wback_region ;
__flush_purge_region = sh2__flush_purge_region ;
__flush_invalidate_region = sh2__flush_invalidate_region ;
}