2010-01-19 15:20:35 +09:00
/*
* arch / sh / mm / tlb - urb . c
*
* TLB entry wiring helpers for URB - equipped parts .
*
* Copyright ( C ) 2010 Matt Fleming
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/mm.h>
# include <linux/io.h>
# include <asm/tlb.h>
# include <asm/mmu_context.h>
/*
* Load the entry for ' addr ' into the TLB and wire the entry .
*/
void tlb_wire_entry ( struct vm_area_struct * vma , unsigned long addr , pte_t pte )
{
unsigned long status , flags ;
int urb ;
local_irq_save ( flags ) ;
status = __raw_readl ( MMUCR ) ;
urb = ( status & MMUCR_URB ) > > MMUCR_URB_SHIFT ;
2010-03-26 11:37:16 +09:00
status & = ~ MMUCR_URC ;
2010-01-19 15:20:35 +09:00
/*
* Make sure we ' re not trying to wire the last TLB entry slot .
*/
BUG_ON ( ! - - urb ) ;
urb = urb % MMUCR_URB_NENTRIES ;
2010-03-26 11:37:16 +09:00
/*
* Insert this entry into the highest non - wired TLB slot ( via
* the URC field ) .
*/
status | = ( urb < < MMUCR_URC_SHIFT ) ;
__raw_writel ( status , MMUCR ) ;
ctrl_barrier ( ) ;
/* Load the entry into the TLB */
__update_tlb ( vma , addr , pte ) ;
/* ... and wire it up. */
status = __raw_readl ( MMUCR ) ;
status & = ~ MMUCR_URB ;
2010-01-19 15:20:35 +09:00
status | = ( urb < < MMUCR_URB_SHIFT ) ;
2010-03-26 11:37:16 +09:00
2010-01-19 15:20:35 +09:00
__raw_writel ( status , MMUCR ) ;
ctrl_barrier ( ) ;
local_irq_restore ( flags ) ;
}
/*
* Unwire the last wired TLB entry .
*
* It should also be noted that it is not possible to wire and unwire
* TLB entries in an arbitrary order . If you wire TLB entry N , followed
* by entry N + 1 , you must unwire entry N + 1 first , then entry N . In this
* respect , it works like a stack or LIFO queue .
*/
void tlb_unwire_entry ( void )
{
unsigned long status , flags ;
int urb ;
local_irq_save ( flags ) ;
status = __raw_readl ( MMUCR ) ;
urb = ( status & MMUCR_URB ) > > MMUCR_URB_SHIFT ;
status & = ~ MMUCR_URB ;
/*
* Make sure we ' re not trying to unwire a TLB entry when none
* have been wired .
*/
BUG_ON ( urb + + = = MMUCR_URB_NENTRIES ) ;
urb = urb % MMUCR_URB_NENTRIES ;
status | = ( urb < < MMUCR_URB_SHIFT ) ;
__raw_writel ( status , MMUCR ) ;
ctrl_barrier ( ) ;
local_irq_restore ( flags ) ;
}