1b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao/* 2b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * linux/arch/unicore32/mm/ioremap.c 3b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 4b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Code specific to PKUnity SoC and UniCore ISA 5b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 6b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Copyright (C) 2001-2010 GUAN Xue-tao 7b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 8b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * This program is free software; you can redistribute it and/or modify 9b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * it under the terms of the GNU General Public License version 2 as 10b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * published by the Free Software Foundation. 11b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 12b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 13b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Re-map IO memory to kernel address space so that we can access it. 14b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 15b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * This allows a driver to remap an arbitrary region of bus memory into 16b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * virtual space. One should *only* use readl, writel, memcpy_toio and 17b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * so on with such remapped areas. 18b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 19b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Because UniCore only has a 32-bit address space we can't address the 20b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * whole of the (physical) PCI space at once. PCI huge-mode addressing 21b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * allows us to circumvent this restriction by splitting PCI space into 22b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * two 2GB chunks and mapping only one at a time into processor memory. 23b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * We use MMU protection domains to trap any attempt to access the bank 24b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * that is not currently mapped. (This isn't fully implemented yet.) 25b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 26b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <linux/module.h> 27b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <linux/errno.h> 28b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <linux/mm.h> 29b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <linux/vmalloc.h> 30b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <linux/io.h> 31b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 32b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <asm/cputype.h> 33b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <asm/cacheflush.h> 34b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <asm/mmu_context.h> 35b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <asm/pgalloc.h> 36b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <asm/tlbflush.h> 37b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <asm/sizes.h> 38b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 39b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include <mach/map.h> 40b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#include "mm.h" 41b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 42b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao/* 43b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Used by ioremap() and iounmap() code to mark (super)section-mapped 44b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * I/O regions in vm_struct->flags field. 45b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 46b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao#define VM_UNICORE_SECTION_MAPPING 0x80000000 47b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 48b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaoint ioremap_page(unsigned long virt, unsigned long phys, 49b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao const struct mem_type *mtype) 50b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 51b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return ioremap_page_range(virt, virt + PAGE_SIZE, phys, 52b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao __pgprot(mtype->prot_pte)); 53b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 54b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaoEXPORT_SYMBOL(ioremap_page); 55b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 56b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao/* 57b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Section support is unsafe on SMP - If you iounmap and ioremap a region, 58b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * the other CPUs will not see this change until their next context switch. 59b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Meanwhile, (eg) if an interrupt comes in on one of those other CPUs 60b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * which requires the new ioremap'd region to be referenced, the CPU will 61b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * reference the _old_ region. 62b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 63b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Note that get_vm_area_caller() allocates a guard 4K page, so we need to 64b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * mask the size back to 4MB aligned or we will overflow in the loop below. 65b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 66b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaostatic void unmap_area_sections(unsigned long virt, unsigned long size) 67b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 68b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned long addr = virt, end = virt + (size & ~(SZ_4M - 1)); 69b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pgd_t *pgd; 70b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 71b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao flush_cache_vunmap(addr, end); 72b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pgd = pgd_offset_k(addr); 73b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao do { 74b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pmd_t pmd, *pmdp = pmd_offset((pud_t *)pgd, addr); 75b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 76b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pmd = *pmdp; 77b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (!pmd_none(pmd)) { 78b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 79b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Clear the PMD from the page table, and 80b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * increment the kvm sequence so others 81b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * notice this change. 82b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 83b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Note: this is still racy on SMP machines. 84b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 85b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pmd_clear(pmdp); 86b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 87b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 88b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Free the page table, if there was one. 89b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 90b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) 91b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pte_free_kernel(&init_mm, pmd_page_vaddr(pmd)); 92b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } 93b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 94b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao addr += PGDIR_SIZE; 95b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pgd++; 96b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } while (addr < end); 97b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 98b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao flush_tlb_kernel_range(virt, end); 99b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 100b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 101b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaostatic int 102b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaoremap_area_sections(unsigned long virt, unsigned long pfn, 103b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao size_t size, const struct mem_type *type) 104b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 105b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned long addr = virt, end = virt + size; 106b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pgd_t *pgd; 107b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 108b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 109b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Remove and free any PTE-based mapping, and 110b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * sync the current kernel mapping. 111b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 112b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unmap_area_sections(virt, size); 113b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 114b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pgd = pgd_offset_k(addr); 115b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao do { 116b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pmd_t *pmd = pmd_offset((pud_t *)pgd, addr); 117b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 118b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao set_pmd(pmd, __pmd(__pfn_to_phys(pfn) | type->prot_sect)); 119b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pfn += SZ_4M >> PAGE_SHIFT; 120b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao flush_pmd_entry(pmd); 121b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 122b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao addr += PGDIR_SIZE; 123b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao pgd++; 124b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } while (addr < end); 125b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 126b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return 0; 127b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 128b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 129b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaovoid __iomem *__uc32_ioremap_pfn_caller(unsigned long pfn, 130b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned long offset, size_t size, unsigned int mtype, void *caller) 131b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 132b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao const struct mem_type *type; 133b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao int err; 134b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned long addr; 135b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao struct vm_struct *area; 136b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 137b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 138b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * High mappings must be section aligned 139b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 140b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SECTION_MASK)) 141b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return NULL; 142b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 143b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 144b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Don't allow RAM to be mapped 145b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 146b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (pfn_valid(pfn)) { 147b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao printk(KERN_WARNING "BUG: Your driver calls ioremap() on\n" 148b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao "system memory. This leads to architecturally\n" 149b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao "unpredictable behaviour, and ioremap() will fail in\n" 150b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao "the next kernel release. Please fix your driver.\n"); 151b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao WARN_ON(1); 152b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } 153b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 154b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao type = get_mem_type(mtype); 155b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (!type) 156b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return NULL; 157b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 158b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 159b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Page align the mapping size, taking account of any offset. 160b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 161b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao size = PAGE_ALIGN(offset + size); 162b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 163b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao area = get_vm_area_caller(size, VM_IOREMAP, caller); 164b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (!area) 165b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return NULL; 166b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao addr = (unsigned long)area->addr; 167b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 168b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) { 169b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao area->flags |= VM_UNICORE_SECTION_MAPPING; 170b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao err = remap_area_sections(addr, pfn, size, type); 171b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } else 172b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao err = ioremap_page_range(addr, addr + size, __pfn_to_phys(pfn), 173b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao __pgprot(type->prot_pte)); 174b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 175b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (err) { 176b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao vunmap((void *)addr); 177b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return NULL; 178b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } 179b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 180b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao flush_cache_vmap(addr, addr + size); 181b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return (void __iomem *) (offset + addr); 182b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 183b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 184b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaovoid __iomem *__uc32_ioremap_caller(unsigned long phys_addr, size_t size, 185b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned int mtype, void *caller) 186b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 187b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned long last_addr; 188b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned long offset = phys_addr & ~PAGE_MASK; 189b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned long pfn = __phys_to_pfn(phys_addr); 190b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 191b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 192b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Don't allow wraparound or zero size 193b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 194b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao last_addr = phys_addr + size - 1; 195b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (!size || last_addr < phys_addr) 196b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return NULL; 197b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 198b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype, caller); 199b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 200b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 201b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao/* 202b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * Remap an arbitrary physical address space into the kernel virtual 203b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * address space. Needed when the kernel wants to access high addresses 204b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * directly. 205b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * 206b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * NOTE! We need to allow non-page-aligned mappings too: we will obviously 207b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * have to convert them into an offset in a page-aligned mapping, but the 208b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * caller shouldn't need to know that small detail. 209b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 210b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaovoid __iomem * 211b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao__uc32_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, 212b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unsigned int mtype) 213b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 214b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype, 215b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao __builtin_return_address(0)); 216b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 217b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaoEXPORT_SYMBOL(__uc32_ioremap_pfn); 218b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 219b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaovoid __iomem * 220b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao__uc32_ioremap(unsigned long phys_addr, size_t size) 221b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 222b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE, 223b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao __builtin_return_address(0)); 224b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 225b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaoEXPORT_SYMBOL(__uc32_ioremap); 226b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 227b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaovoid __iomem * 228b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao__uc32_ioremap_cached(unsigned long phys_addr, size_t size) 229b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 230b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE_CACHED, 231b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao __builtin_return_address(0)); 232b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 233b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaoEXPORT_SYMBOL(__uc32_ioremap_cached); 234b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 235b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaovoid __uc32_iounmap(volatile void __iomem *io_addr) 236b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao{ 237b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr); 238b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao struct vm_struct **p, *tmp; 239b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 240b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao /* 241b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * If this is a section based mapping we need to handle it 242b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * specially as the VM subsystem does not know how to handle 243b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * such a beast. We need the lock here b/c we need to clear 244b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * all the mappings before the area can be reclaimed 245b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao * by someone else. 246b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao */ 247b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao write_lock(&vmlist_lock); 248b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) { 249b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) { 250b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao if (tmp->flags & VM_UNICORE_SECTION_MAPPING) { 251b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao unmap_area_sections((unsigned long)tmp->addr, 252b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao tmp->size); 253b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } 254b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao break; 255b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } 256b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao } 257b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao write_unlock(&vmlist_lock); 258b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao 259b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao vunmap(addr); 260b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetao} 261b50f1704e9c441c58cf6dc05e72953ca30e1d4d2GuanXuetaoEXPORT_SYMBOL(__uc32_iounmap); 262