ARM: implement ioremap_prot
authorGrazvydas Ignotas <notasas@gmail.com>
Sat, 7 Feb 2015 19:20:35 +0000 (21:20 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Fri, 20 Feb 2015 22:05:26 +0000 (00:05 +0200)
arch/arm/Kconfig
arch/arm/include/asm/io.h
arch/arm/include/asm/pgtable-2level-types.h
arch/arm/mm/ioremap.c

index 3ea62da..870794a 100644 (file)
@@ -30,6 +30,7 @@ config ARM
        select HAVE_C_RECORDMCOUNT
        select HAVE_GENERIC_HARDIRQS
        select HAVE_SPARSE_IRQ
+       select HAVE_IOREMAP_PROT
        select GENERIC_IRQ_SHOW
        select CPU_PM if (SUSPEND || CPU_IDLE)
        help
index 065d100..cb81b3b 100644 (file)
@@ -83,6 +83,9 @@ extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
 extern void __iomem *__arm_ioremap_exec(unsigned long, size_t, bool cached);
 extern void __iounmap(volatile void __iomem *addr);
 
+extern void __iomem *ioremap_prot(resource_size_t, unsigned long size,
+       unsigned long prot_val);
+
 /*
  * Bad read/write accesses...
  */
index 66cb5b0..93ce673 100644 (file)
@@ -64,4 +64,6 @@ typedef pteval_t pgprot_t;
 
 #endif /* STRICT_MM_TYPECHECKS */
 
+#define pte_pgprot(pte)        __pgprot(pte_val(pte))
+
 #endif /* _ASM_PGTABLE_2LEVEL_TYPES_H */
index 80632e8..c6f20dc 100644 (file)
@@ -335,6 +335,43 @@ __arm_ioremap_exec(unsigned long phys_addr, size_t size, bool cached)
                        __builtin_return_address(0));
 }
 
+void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
+                               unsigned long prot_val)
+{
+       const struct mem_type *type;
+       unsigned long addr;
+       struct vm_struct * area;
+       pteval_t prot_pte;
+       int err;
+
+       size = PAGE_ALIGN(size);
+
+       type = get_mem_type(MT_DEVICE);
+       if (!type)
+               return NULL;
+
+       prot_pte = type->prot_pte & ~L_PTE_MT_MASK;
+       prot_pte |= prot_val & L_PTE_MT_MASK;
+
+       area = get_vm_area_caller(size, VM_IOREMAP,
+                                 __builtin_return_address(0));
+       if (!area)
+               return NULL;
+       addr = (unsigned long)area->addr;
+
+       err = ioremap_page_range(addr, addr + size, phys_addr,
+                                __pgprot(prot_pte));
+       if (err) {
+               vunmap((void *)addr);
+               return NULL;
+       }
+
+       flush_cache_vmap(addr, addr + size);
+       return (void __iomem *)addr;
+}
+
+EXPORT_SYMBOL(ioremap_prot);
+
 void __iounmap(volatile void __iomem *io_addr)
 {
        void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);