Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 31705
b: refs/heads/master
c: a069c89
h: refs/heads/master
i:
  31703: d5bd09f
v: v3
  • Loading branch information
Lennert Buytenhek authored and Russell King committed Jul 1, 2006
1 parent e838829 commit 41107e6
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ae95bfbb2b67eba5d67a0478a8715682a87e2616
refs/heads/master: a069c896d0d6c028581089da7a9a9037a63c2803
66 changes: 63 additions & 3 deletions trunk/arch/arm/mm/ioremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
#include <asm/sizes.h>

/*
* Used by ioremap() and iounmap() code to mark section-mapped I/O regions
* in vm_struct->flags field.
* Used by ioremap() and iounmap() code to mark (super)section-mapped
* I/O regions in vm_struct->flags field.
*/
#define VM_ARM_SECTION_MAPPING 0x80000000

Expand Down Expand Up @@ -233,6 +233,54 @@ remap_area_sections(unsigned long virt, unsigned long pfn,

return 0;
}

static int
remap_area_supersections(unsigned long virt, unsigned long pfn,
unsigned long size, unsigned long flags)
{
unsigned long prot, addr = virt, end = virt + size;
pgd_t *pgd;

/*
* Remove and free any PTE-based mapping, and
* sync the current kernel mapping.
*/
unmap_area_sections(virt, size);

prot = PMD_TYPE_SECT | PMD_SECT_SUPER | PMD_SECT_AP_WRITE |
PMD_DOMAIN(DOMAIN_IO) |
(flags & (L_PTE_CACHEABLE | L_PTE_BUFFERABLE));

/*
* ARMv6 and above need XN set to prevent speculative prefetches
* hitting IO.
*/
if (cpu_architecture() >= CPU_ARCH_ARMv6)
prot |= PMD_SECT_XN;

pgd = pgd_offset_k(virt);
do {
unsigned long super_pmd_val, i;

super_pmd_val = __pfn_to_phys(pfn) | prot;
super_pmd_val |= ((pfn >> (32 - PAGE_SHIFT)) & 0xf) << 20;

for (i = 0; i < 8; i++) {
pmd_t *pmd = pmd_offset(pgd, addr);

pmd[0] = __pmd(super_pmd_val);
pmd[1] = __pmd(super_pmd_val);
flush_pmd_entry(pmd);

addr += PGDIR_SIZE;
pgd++;
}

pfn += SUPERSECTION_SIZE >> PAGE_SHIFT;
} while (addr < end);

return 0;
}
#endif


Expand All @@ -255,14 +303,26 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
int err;
unsigned long addr;
struct vm_struct * area;
unsigned int cr = get_cr();

/*
* High mappings must be supersection aligned
*/
if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK))
return NULL;

area = get_vm_area(size, VM_IOREMAP);
if (!area)
return NULL;
addr = (unsigned long)area->addr;

#ifndef CONFIG_SMP
if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
if ((((cpu_architecture() >= CPU_ARCH_ARMv6) && (cr & CR_XP)) ||
cpu_is_xsc3()) &&
!((__pfn_to_phys(pfn) | size | addr) & ~SUPERSECTION_MASK)) {
area->flags |= VM_ARM_SECTION_MAPPING;
err = remap_area_supersections(addr, pfn, size, flags);
} else if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
area->flags |= VM_ARM_SECTION_MAPPING;
err = remap_area_sections(addr, pfn, size, flags);
} else
Expand Down
4 changes: 2 additions & 2 deletions trunk/include/asm-arm/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@
#define XIP_VIRT_ADDR(physaddr) (MODULE_START + ((physaddr) & 0x000fffff))

/*
* Allow 2MB-aligned ioremap pages
* Allow 16MB-aligned ioremap pages
*/
#define IOREMAP_MAX_ORDER 21
#define IOREMAP_MAX_ORDER 24

#else /* CONFIG_MMU */

Expand Down

0 comments on commit 41107e6

Please sign in to comment.