Commit 6eb3c735 authored by Paul Mundt's avatar Paul Mundt

sh: fixed virt/phys mapping helpers for PMB.

This moves the pmb_remap_caller() mapping logic out in to
pmb_bolt_mapping(), which enables us to establish fixed mappings in
places such as the NUMA code.
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 4cfa8e75
...@@ -270,60 +270,19 @@ static void set_pmb_entry(struct pmb_entry *pmbe) ...@@ -270,60 +270,19 @@ static void set_pmb_entry(struct pmb_entry *pmbe)
int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys, int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
unsigned long size, pgprot_t prot) unsigned long size, pgprot_t prot)
{
return 0;
}
void __iomem *pmb_remap_caller(phys_addr_t phys, unsigned long size,
pgprot_t prot, void *caller)
{ {
struct pmb_entry *pmbp, *pmbe; struct pmb_entry *pmbp, *pmbe;
unsigned long pmb_flags; unsigned long pmb_flags;
int i, mapped; int i, mapped;
unsigned long orig_addr, vaddr;
phys_addr_t offset, last_addr;
phys_addr_t align_mask;
unsigned long aligned;
struct vm_struct *area;
if (!pmb_iomapping_enabled) if (!pmb_addr_valid(vaddr, size))
return NULL; return -EFAULT;
/*
* Small mappings need to go through the TLB.
*/
if (size < SZ_16M)
return ERR_PTR(-EINVAL);
if (!pmb_prot_valid(prot))
return ERR_PTR(-EINVAL);
pmbp = NULL;
pmb_flags = pgprot_to_pmb_flags(prot); pmb_flags = pgprot_to_pmb_flags(prot);
mapped = 0; pmbp = NULL;
for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
if (size >= pmb_sizes[i].size)
break;
last_addr = phys + size;
align_mask = ~(pmb_sizes[i].size - 1);
offset = phys & ~align_mask;
phys &= align_mask;
aligned = ALIGN(last_addr, pmb_sizes[i].size) - phys;
area = __get_vm_area_caller(aligned, VM_IOREMAP, uncached_end,
P3SEG, caller);
if (!area)
return NULL;
area->phys_addr = phys;
orig_addr = vaddr = (unsigned long)area->addr;
if (!pmb_addr_valid(vaddr, aligned))
return ERR_PTR(-EFAULT);
again: again:
for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) { for (i = mapped = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
unsigned long flags; unsigned long flags;
if (size < pmb_sizes[i].size) if (size < pmb_sizes[i].size)
...@@ -333,7 +292,7 @@ again: ...@@ -333,7 +292,7 @@ again:
PMB_NO_ENTRY); PMB_NO_ENTRY);
if (IS_ERR(pmbe)) { if (IS_ERR(pmbe)) {
pmb_unmap_entry(pmbp, mapped); pmb_unmap_entry(pmbp, mapped);
return pmbe; return PTR_ERR(pmbe);
} }
spin_lock_irqsave(&pmbe->lock, flags); spin_lock_irqsave(&pmbe->lock, flags);
...@@ -372,6 +331,52 @@ again: ...@@ -372,6 +331,52 @@ again:
if (size >= SZ_16M) if (size >= SZ_16M)
goto again; goto again;
return 0;
}
void __iomem *pmb_remap_caller(phys_addr_t phys, unsigned long size,
pgprot_t prot, void *caller)
{
unsigned long orig_addr, vaddr;
phys_addr_t offset, last_addr;
phys_addr_t align_mask;
unsigned long aligned;
struct vm_struct *area;
int i, ret;
if (!pmb_iomapping_enabled)
return NULL;
/*
* Small mappings need to go through the TLB.
*/
if (size < SZ_16M)
return ERR_PTR(-EINVAL);
if (!pmb_prot_valid(prot))
return ERR_PTR(-EINVAL);
for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
if (size >= pmb_sizes[i].size)
break;
last_addr = phys + size;
align_mask = ~(pmb_sizes[i].size - 1);
offset = phys & ~align_mask;
phys &= align_mask;
aligned = ALIGN(last_addr, pmb_sizes[i].size) - phys;
area = __get_vm_area_caller(aligned, VM_IOREMAP, uncached_end,
P3SEG, caller);
if (!area)
return NULL;
area->phys_addr = phys;
orig_addr = vaddr = (unsigned long)area->addr;
ret = pmb_bolt_mapping(vaddr, phys, size, prot);
if (ret != 0)
return ERR_PTR(ret);
return (void __iomem *)(offset + (char *)orig_addr); return (void __iomem *)(offset + (char *)orig_addr);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment