1bb29c677SPaul Mundt /*
2bb29c677SPaul Mundt * arch/sh/mm/tlb-urb.c
3bb29c677SPaul Mundt *
4bb29c677SPaul Mundt * TLB entry wiring helpers for URB-equipped parts.
5bb29c677SPaul Mundt *
6bb29c677SPaul Mundt * Copyright (C) 2010 Matt Fleming
7bb29c677SPaul Mundt *
8bb29c677SPaul Mundt * This file is subject to the terms and conditions of the GNU General Public
9bb29c677SPaul Mundt * License. See the file "COPYING" in the main directory of this archive
10bb29c677SPaul Mundt * for more details.
11bb29c677SPaul Mundt */
12bb29c677SPaul Mundt #include <linux/mm.h>
13bb29c677SPaul Mundt #include <linux/io.h>
14bb29c677SPaul Mundt #include <asm/tlb.h>
15bb29c677SPaul Mundt #include <asm/mmu_context.h>
16bb29c677SPaul Mundt
17bb29c677SPaul Mundt /*
18bb29c677SPaul Mundt * Load the entry for 'addr' into the TLB and wire the entry.
19bb29c677SPaul Mundt */
tlb_wire_entry(struct vm_area_struct * vma,unsigned long addr,pte_t pte)20bb29c677SPaul Mundt void tlb_wire_entry(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
21bb29c677SPaul Mundt {
22bb29c677SPaul Mundt unsigned long status, flags;
23bb29c677SPaul Mundt int urb;
24bb29c677SPaul Mundt
25bb29c677SPaul Mundt local_irq_save(flags);
26bb29c677SPaul Mundt
27bb29c677SPaul Mundt status = __raw_readl(MMUCR);
28bb29c677SPaul Mundt urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT;
29*4539282dSMatt Fleming status &= ~MMUCR_URC;
30bb29c677SPaul Mundt
31bb29c677SPaul Mundt /*
32bb29c677SPaul Mundt * Make sure we're not trying to wire the last TLB entry slot.
33bb29c677SPaul Mundt */
34bb29c677SPaul Mundt BUG_ON(!--urb);
35bb29c677SPaul Mundt
36bb29c677SPaul Mundt urb = urb % MMUCR_URB_NENTRIES;
37bb29c677SPaul Mundt
38*4539282dSMatt Fleming /*
39*4539282dSMatt Fleming * Insert this entry into the highest non-wired TLB slot (via
40*4539282dSMatt Fleming * the URC field).
41*4539282dSMatt Fleming */
42*4539282dSMatt Fleming status |= (urb << MMUCR_URC_SHIFT);
43*4539282dSMatt Fleming __raw_writel(status, MMUCR);
44*4539282dSMatt Fleming ctrl_barrier();
45*4539282dSMatt Fleming
46*4539282dSMatt Fleming /* Load the entry into the TLB */
47*4539282dSMatt Fleming __update_tlb(vma, addr, pte);
48*4539282dSMatt Fleming
49*4539282dSMatt Fleming /* ... and wire it up. */
50*4539282dSMatt Fleming status = __raw_readl(MMUCR);
51*4539282dSMatt Fleming
52*4539282dSMatt Fleming status &= ~MMUCR_URB;
53bb29c677SPaul Mundt status |= (urb << MMUCR_URB_SHIFT);
54*4539282dSMatt Fleming
55bb29c677SPaul Mundt __raw_writel(status, MMUCR);
56bb29c677SPaul Mundt ctrl_barrier();
57bb29c677SPaul Mundt
58bb29c677SPaul Mundt local_irq_restore(flags);
59bb29c677SPaul Mundt }
60bb29c677SPaul Mundt
61bb29c677SPaul Mundt /*
62bb29c677SPaul Mundt * Unwire the last wired TLB entry.
63bb29c677SPaul Mundt *
64bb29c677SPaul Mundt * It should also be noted that it is not possible to wire and unwire
65bb29c677SPaul Mundt * TLB entries in an arbitrary order. If you wire TLB entry N, followed
66bb29c677SPaul Mundt * by entry N+1, you must unwire entry N+1 first, then entry N. In this
67bb29c677SPaul Mundt * respect, it works like a stack or LIFO queue.
68bb29c677SPaul Mundt */
tlb_unwire_entry(void)69bb29c677SPaul Mundt void tlb_unwire_entry(void)
70bb29c677SPaul Mundt {
71bb29c677SPaul Mundt unsigned long status, flags;
72bb29c677SPaul Mundt int urb;
73bb29c677SPaul Mundt
74bb29c677SPaul Mundt local_irq_save(flags);
75bb29c677SPaul Mundt
76bb29c677SPaul Mundt status = __raw_readl(MMUCR);
77bb29c677SPaul Mundt urb = (status & MMUCR_URB) >> MMUCR_URB_SHIFT;
78bb29c677SPaul Mundt status &= ~MMUCR_URB;
79bb29c677SPaul Mundt
80bb29c677SPaul Mundt /*
81bb29c677SPaul Mundt * Make sure we're not trying to unwire a TLB entry when none
82bb29c677SPaul Mundt * have been wired.
83bb29c677SPaul Mundt */
84bb29c677SPaul Mundt BUG_ON(urb++ == MMUCR_URB_NENTRIES);
85bb29c677SPaul Mundt
86bb29c677SPaul Mundt urb = urb % MMUCR_URB_NENTRIES;
87bb29c677SPaul Mundt
88bb29c677SPaul Mundt status |= (urb << MMUCR_URB_SHIFT);
89bb29c677SPaul Mundt __raw_writel(status, MMUCR);
90bb29c677SPaul Mundt ctrl_barrier();
91bb29c677SPaul Mundt
92bb29c677SPaul Mundt local_irq_restore(flags);
93bb29c677SPaul Mundt }
94