summaryrefslogtreecommitdiff
path: root/arch/sh/mm/init.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-18 20:42:39 +0900
committerPaul Mundt <lethal@linux-sh.org>2010-01-18 20:42:39 +0900
commit8faba6121566248330e738d25a2c43d7500fb9f0 (patch)
tree9cb09b2ec00b504dd24e1272126a22cd365e7282 /arch/sh/mm/init.c
parent4291b730cd0f0cf98a90d946b6cabbd804397350 (diff)
parent78bf04fc96f509474c6b443b515d6b79bb7bf584 (diff)
Merge branch 'sh/ioremap-fixed'
Diffstat (limited to 'arch/sh/mm/init.c')
-rw-r--r--arch/sh/mm/init.c44
1 files changed, 40 insertions, 4 deletions
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index d5fb014279ad2..30a9b530d4568 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -39,7 +39,7 @@ unsigned long cached_to_uncached = P2SEG - P1SEG;
#endif
#ifdef CONFIG_MMU
-static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
+static pte_t *__get_pte_phys(unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
@@ -49,22 +49,30 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
pgd = pgd_offset_k(addr);
if (pgd_none(*pgd)) {
pgd_ERROR(*pgd);
- return;
+ return NULL;
}
pud = pud_alloc(NULL, pgd, addr);
if (unlikely(!pud)) {
pud_ERROR(*pud);
- return;
+ return NULL;
}
pmd = pmd_alloc(NULL, pud, addr);
if (unlikely(!pmd)) {
pmd_ERROR(*pmd);
- return;
+ return NULL;
}
pte = pte_offset_kernel(pmd, addr);
+ return pte;
+}
+
+static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
+{
+ pte_t *pte;
+
+ pte = __get_pte_phys(addr);
if (!pte_none(*pte)) {
pte_ERROR(*pte);
return;
@@ -72,6 +80,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
local_flush_tlb_one(get_asid(), addr);
+
+ if (pgprot_val(prot) & _PAGE_WIRED)
+ tlb_wire_entry(NULL, addr, *pte);
+}
+
+static void clear_pte_phys(unsigned long addr, pgprot_t prot)
+{
+ pte_t *pte;
+
+ pte = __get_pte_phys(addr);
+
+ if (pgprot_val(prot) & _PAGE_WIRED)
+ tlb_unwire_entry();
+
+ set_pte(pte, pfn_pte(0, __pgprot(0)));
+ local_flush_tlb_one(get_asid(), addr);
}
/*
@@ -101,6 +125,18 @@ void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
set_pte_phys(address, phys, prot);
}
+void __clear_fixmap(enum fixed_addresses idx, pgprot_t prot)
+{
+ unsigned long address = __fix_to_virt(idx);
+
+ if (idx >= __end_of_fixed_addresses) {
+ BUG();
+ return;
+ }
+
+ clear_pte_phys(address, prot);
+}
+
void __init page_table_range_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{