diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-26 16:54:27 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-26 16:54:27 -0800 |
commit | 64d497f55379b1e320a08ec2426468d96f5642ec (patch) | |
tree | 22b9ab3c5e69c5cc2728cbc2ca7fc7623beef8f1 /arch/sh/mm/tlb-urb.c | |
parent | 37d4008484977f60d5d37499a2670c79b214dd46 (diff) | |
parent | b5f5fe80fa98a60daa0fa94512d1599b1e26674c (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (187 commits)
sh: remove dead LED code for migo-r and ms7724se
sh: ecovec build fix for CONFIG_I2C=n
sh: ecovec r-standby support
sh: ms7724se r-standby support
sh: SH-Mobile R-standby register save/restore
clocksource: Fix up a registration/IRQ race in the sh drivers.
sh: ms7724: modify scan_timing for KEYSC
sh: ms7724: Add sh_sir support
sh: mach-ecovec24: Add sh_sir support
sh: wire up SET/GET_UNALIGN_CTL.
sh: allow alignment fault mode to be configured at kernel boot.
sh: sh7724: Update FSI/SPU2 clock
sh: always enable sh7724 vpu_clk and set to 166MHz on Ecovec
sh: add sh7724 kick callback to clk_div4_table
sh: introduce struct clk_div4_table
sh: clock-cpg div4 set_rate() shift fix
sh: Turn on speculative return for SH7785 and SH7786
sh: Merge legacy and dynamic PMB modes.
sh: Use uncached I/O helpers in PMB setup.
sh: Provide uncached I/O helpers.
...
Diffstat (limited to 'arch/sh/mm/tlb-urb.c')
-rw-r--r-- | arch/sh/mm/tlb-urb.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/sh/mm/tlb-urb.c b/arch/sh/mm/tlb-urb.c new file mode 100644 index 00000000000..bb5b9098956 --- /dev/null +++ b/arch/sh/mm/tlb-urb.c @@ -0,0 +1,81 @@ +/* + * 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); + + /* Load the entry into the TLB */ + __update_tlb(vma, addr, pte); + + /* ... and wire it up. */ + status = __raw_readl(MMUCR); + urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT; + status &= ~MMUCR_URB; + + /* + * Make sure we're not trying to wire the last TLB entry slot. + */ + BUG_ON(!--urb); + + urb = urb % MMUCR_URB_NENTRIES; + + status |= (urb << MMUCR_URB_SHIFT); + __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); +} |