linux/arch/nds32/mm/ioremap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2005-2017 Andes Technology Corporation
   3
   4#include <linux/vmalloc.h>
   5#include <linux/io.h>
   6#include <linux/mm.h>
   7#include <asm/pgtable.h>
   8
   9void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
  10
  11static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
  12                                      void *caller)
  13{
  14        struct vm_struct *area;
  15        unsigned long addr, offset, last_addr;
  16        pgprot_t prot;
  17
  18        /* Don't allow wraparound or zero size */
  19        last_addr = phys_addr + size - 1;
  20        if (!size || last_addr < phys_addr)
  21                return NULL;
  22
  23        /*
  24         * Mappings have to be page-aligned
  25         */
  26        offset = phys_addr & ~PAGE_MASK;
  27        phys_addr &= PAGE_MASK;
  28        size = PAGE_ALIGN(last_addr + 1) - phys_addr;
  29
  30        /*
  31         * Ok, go for it..
  32         */
  33        area = get_vm_area_caller(size, VM_IOREMAP, caller);
  34        if (!area)
  35                return NULL;
  36
  37        area->phys_addr = phys_addr;
  38        addr = (unsigned long)area->addr;
  39        prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
  40                        _PAGE_G | _PAGE_C_DEV);
  41        if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
  42                vunmap((void *)addr);
  43                return NULL;
  44        }
  45        return (__force void __iomem *)(offset + (char *)addr);
  46
  47}
  48
  49void __iomem *ioremap(phys_addr_t phys_addr, size_t size)
  50{
  51        return __ioremap_caller(phys_addr, size,
  52                                __builtin_return_address(0));
  53}
  54
  55EXPORT_SYMBOL(ioremap);
  56
  57void iounmap(volatile void __iomem * addr)
  58{
  59        vunmap((void *)(PAGE_MASK & (unsigned long)addr));
  60}
  61
  62EXPORT_SYMBOL(iounmap);
  63