2019-05-29 07:12:41 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2011-10-31 18:50:51 -05:00
/*
* Cache management functions for Hexagon
*
2012-09-19 16:22:02 -05:00
* Copyright ( c ) 2010 - 2011 , The Linux Foundation . All rights reserved .
2011-10-31 18:50:51 -05:00
*/
# include <linux/mm.h>
# include <asm/cacheflush.h>
# include <asm/hexagon_vm.h>
# define spanlines(start, end) \
( ( ( end - ( start & ~ ( LINESIZE - 1 ) ) ) > > LINEBITS ) + 1 )
void flush_dcache_range ( unsigned long start , unsigned long end )
{
unsigned long lines = spanlines ( start , end - 1 ) ;
unsigned long i , flags ;
start & = ~ ( LINESIZE - 1 ) ;
local_irq_save ( flags ) ;
for ( i = 0 ; i < lines ; i + + ) {
__asm__ __volatile__ (
" dccleaninva(%0); "
:
: " r " ( start )
) ;
start + = LINESIZE ;
}
local_irq_restore ( flags ) ;
}
void flush_icache_range ( unsigned long start , unsigned long end )
{
unsigned long lines = spanlines ( start , end - 1 ) ;
unsigned long i , flags ;
start & = ~ ( LINESIZE - 1 ) ;
local_irq_save ( flags ) ;
for ( i = 0 ; i < lines ; i + + ) {
__asm__ __volatile__ (
" dccleana(%0); "
" icinva(%0); "
:
: " r " ( start )
) ;
start + = LINESIZE ;
}
__asm__ __volatile__ (
" isync "
) ;
local_irq_restore ( flags ) ;
}
2014-08-29 15:19:09 -07:00
EXPORT_SYMBOL ( flush_icache_range ) ;
2011-10-31 18:50:51 -05:00
void hexagon_clean_dcache_range ( unsigned long start , unsigned long end )
{
unsigned long lines = spanlines ( start , end - 1 ) ;
unsigned long i , flags ;
start & = ~ ( LINESIZE - 1 ) ;
local_irq_save ( flags ) ;
for ( i = 0 ; i < lines ; i + + ) {
__asm__ __volatile__ (
" dccleana(%0); "
:
: " r " ( start )
) ;
start + = LINESIZE ;
}
local_irq_restore ( flags ) ;
}
void hexagon_inv_dcache_range ( unsigned long start , unsigned long end )
{
unsigned long lines = spanlines ( start , end - 1 ) ;
unsigned long i , flags ;
start & = ~ ( LINESIZE - 1 ) ;
local_irq_save ( flags ) ;
for ( i = 0 ; i < lines ; i + + ) {
__asm__ __volatile__ (
" dcinva(%0); "
:
: " r " ( start )
) ;
start + = LINESIZE ;
}
local_irq_restore ( flags ) ;
}
/*
* This is just really brutal and shouldn ' t be used anyways ,
* especially on V2 . Left here just in case .
*/
void flush_cache_all_hexagon ( void )
{
unsigned long flags ;
local_irq_save ( flags ) ;
__vmcache_ickill ( ) ;
__vmcache_dckill ( ) ;
__vmcache_l2kill ( ) ;
local_irq_restore ( flags ) ;
mb ( ) ;
}
2014-12-09 14:21:45 -08:00
void copy_to_user_page ( struct vm_area_struct * vma , struct page * page ,
unsigned long vaddr , void * dst , void * src , int len )
{
memcpy ( dst , src , len ) ;
if ( vma - > vm_flags & VM_EXEC ) {
flush_icache_range ( ( unsigned long ) dst ,
( unsigned long ) dst + len ) ;
}
}