2019-05-28 10:10:14 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-16 15:20:36 -07:00
/*
* arch / sh / mm / cache - sh2 . c
*
* Copyright ( C ) 2002 Paul Mundt
2008-08-04 16:33:47 +09:00
* Copyright ( C ) 2008 Yoshinori Sato
2005-04-16 15:20:36 -07:00
*/
2006-11-05 15:40:13 +09:00
2005-04-16 15:20:36 -07: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 12:35:15 +09:00
static void sh2__flush_wback_region ( void * start , int size )
2005-04-16 15:20:36 -07:00
{
2006-11-05 15:40:13 +09: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 16:33:47 +09:00
unsigned long addr = CACHE_OC_ADDRESS_ARRAY | ( v & 0x00000ff0 ) ;
int way ;
for ( way = 0 ; way < 4 ; way + + ) {
2010-01-26 12:58:40 +09:00
unsigned long data = __raw_readl ( addr | ( way < < 12 ) ) ;
2008-08-04 16:33:47 +09:00
if ( ( data & CACHE_PHYSADDR_MASK ) = = ( v & CACHE_PHYSADDR_MASK ) ) {
data & = ~ SH_CACHE_UPDATED ;
2010-01-26 12:58:40 +09:00
__raw_writel ( data , addr | ( way < < 12 ) ) ;
2008-08-04 16:33:47 +09:00
}
}
2006-11-05 15:40:13 +09:00
}
}
2009-08-15 12:35:15 +09:00
static void sh2__flush_purge_region ( void * start , int size )
2006-11-05 15:40:13 +09: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 16:33:47 +09:00
for ( v = begin ; v < end ; v + = L1_CACHE_BYTES )
2010-01-26 12:58:40 +09:00
__raw_writel ( ( v & CACHE_PHYSADDR_MASK ) ,
2008-08-04 16:33:47 +09:00
CACHE_OC_ADDRESS_ARRAY | ( v & 0x00000ff0 ) | 0x00000008 ) ;
2006-11-05 15:40:13 +09:00
}
2009-08-15 12:35:15 +09:00
static void sh2__flush_invalidate_region ( void * start , int size )
2006-11-05 15:40:13 +09:00
{
2008-08-04 16:33:47 +09: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-03 15:38:33 -08:00
ccr = __raw_readl ( SH_CCR ) ;
2008-08-04 16:33:47 +09:00
ccr | = CCR_CACHE_INVALIDATE ;
2014-03-03 15:38:33 -08:00
__raw_writel ( ccr , SH_CCR ) ;
2008-08-04 16:33:47 +09:00
back_to_cached ( ) ;
local_irq_restore ( flags ) ;
# else
2006-11-05 15:40:13 +09: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-16 15:20:36 -07:00
2008-08-04 16:33:47 +09:00
for ( v = begin ; v < end ; v + = L1_CACHE_BYTES )
2010-01-26 12:58:40 +09:00
__raw_writel ( ( v & CACHE_PHYSADDR_MASK ) ,
2008-08-04 16:33:47 +09:00
CACHE_OC_ADDRESS_ARRAY | ( v & 0x00000ff0 ) | 0x00000008 ) ;
# endif
}
2009-08-15 12:35:15 +09: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 ;
}