summaryrefslogtreecommitdiff
path: root/arch/sh/mm/pmb.c
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-10-06 21:22:33 +0000
committerPaul Mundt <lethal@linux-sh.org>2009-10-10 21:52:34 +0900
commit20b5014b3e5fe7b874a3f6a1dc03b0c21cb222cd (patch)
tree7b14d3c6f7004ca86e444c7237a022a143405e7f /arch/sh/mm/pmb.c
parentef269b32763b22100eda9c0bf99d462c6cd65377 (diff)
sh: Fold fixed-PMB support into dynamic PMB support
The initialisation process differs for CONFIG_PMB and for CONFIG_PMB_FIXED. For CONFIG_PMB_FIXED we need to register the PMB entries that were allocated by the bootloader. Signed-off-by: Matt Fleming <matt@console-pimps.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/mm/pmb.c')
-rw-r--r--arch/sh/mm/pmb.c65
1 files changed, 60 insertions, 5 deletions
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 7e64f6d960c5..280f6a166035 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -70,14 +70,20 @@ repeat:
}
static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
- unsigned long flags)
+ unsigned long flags, int entry)
{
struct pmb_entry *pmbe;
int pos;
- pos = pmb_alloc_entry();
- if (pos < 0)
- return ERR_PTR(pos);
+ if (entry == PMB_NO_ENTRY) {
+ pos = pmb_alloc_entry();
+ if (pos < 0)
+ return ERR_PTR(pos);
+ } else {
+ if (test_bit(entry, &pmb_map))
+ return ERR_PTR(-ENOSPC);
+ pos = entry;
+ }
pmbe = &pmb_entry_list[pos];
if (!pmbe)
@@ -187,7 +193,8 @@ again:
if (size < pmb_sizes[i].size)
continue;
- pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag);
+ pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag,
+ PMB_NO_ENTRY);
if (IS_ERR(pmbe)) {
err = PTR_ERR(pmbe);
goto out;
@@ -272,6 +279,7 @@ static void __pmb_unmap(struct pmb_entry *pmbe)
} while (pmbe);
}
+#ifdef CONFIG_PMB
int __uses_jump_to_uncached pmb_init(void)
{
unsigned int i;
@@ -309,6 +317,53 @@ int __uses_jump_to_uncached pmb_init(void)
return 0;
}
+#else
+int __uses_jump_to_uncached pmb_init(void)
+{
+ int i;
+ unsigned long addr, data;
+
+ jump_to_uncached();
+
+ for (i = 0; i < PMB_ENTRY_MAX; i++) {
+ struct pmb_entry *pmbe;
+ unsigned long vpn, ppn, flags;
+
+ addr = PMB_DATA + (i << PMB_E_SHIFT);
+ data = ctrl_inl(addr);
+ if (!(data & PMB_V))
+ continue;
+
+ if (data & PMB_C) {
+#if defined(CONFIG_CACHE_WRITETHROUGH)
+ data |= PMB_WT;
+#elif defined(CONFIG_CACHE_WRITEBACK)
+ data &= ~PMB_WT;
+#else
+ data &= ~(PMB_C | PMB_WT);
+#endif
+ }
+ ctrl_outl(data, addr);
+
+ ppn = data & PMB_PFN_MASK;
+
+ flags = data & (PMB_C | PMB_WT | PMB_UB);
+ flags |= data & PMB_SZ_MASK;
+
+ addr = PMB_ADDR + (i << PMB_E_SHIFT);
+ data = ctrl_inl(addr);
+
+ vpn = data & PMB_PFN_MASK;
+
+ pmbe = pmb_alloc(vpn, ppn, flags, i);
+ WARN_ON(IS_ERR(pmbe));
+ }
+
+ back_to_cached();
+
+ return 0;
+}
+#endif /* CONFIG_PMB */
static int pmb_seq_show(struct seq_file *file, void *iter)
{