Root/lib/ioremap.c

Source at commit b386be689295730688885552666ea40b2e639b14 created 8 years 11 months ago.
By Maarten ter Huurne, Revert "MIPS: JZ4740: reset: Initialize hibernate wakeup counters."
1/*
2 * Re-map IO memory to kernel address space so that we can access it.
3 * This is needed for high PCI addresses that aren't mapped in the
4 * 640k-1MB IO memory area on PC's
5 *
6 * (C) Copyright 1995 1996 Linus Torvalds
7 */
8#include <linux/vmalloc.h>
9#include <linux/mm.h>
10#include <linux/sched.h>
11#include <linux/io.h>
12#include <linux/module.h>
13#include <asm/cacheflush.h>
14#include <asm/pgtable.h>
15
16static int ioremap_pte_range(pmd_t *pmd, unsigned long addr,
17        unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
18{
19    pte_t *pte;
20    u64 pfn;
21
22    pfn = phys_addr >> PAGE_SHIFT;
23    pte = pte_alloc_kernel(pmd, addr);
24    if (!pte)
25        return -ENOMEM;
26    do {
27        BUG_ON(!pte_none(*pte));
28        set_pte_at(&init_mm, addr, pte, pfn_pte(pfn, prot));
29        pfn++;
30    } while (pte++, addr += PAGE_SIZE, addr != end);
31    return 0;
32}
33
34static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr,
35        unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
36{
37    pmd_t *pmd;
38    unsigned long next;
39
40    phys_addr -= addr;
41    pmd = pmd_alloc(&init_mm, pud, addr);
42    if (!pmd)
43        return -ENOMEM;
44    do {
45        next = pmd_addr_end(addr, end);
46        if (ioremap_pte_range(pmd, addr, next, phys_addr + addr, prot))
47            return -ENOMEM;
48    } while (pmd++, addr = next, addr != end);
49    return 0;
50}
51
52static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
53        unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
54{
55    pud_t *pud;
56    unsigned long next;
57
58    phys_addr -= addr;
59    pud = pud_alloc(&init_mm, pgd, addr);
60    if (!pud)
61        return -ENOMEM;
62    do {
63        next = pud_addr_end(addr, end);
64        if (ioremap_pmd_range(pud, addr, next, phys_addr + addr, prot))
65            return -ENOMEM;
66    } while (pud++, addr = next, addr != end);
67    return 0;
68}
69
70int ioremap_page_range(unsigned long addr,
71               unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
72{
73    pgd_t *pgd;
74    unsigned long start;
75    unsigned long next;
76    int err;
77
78    BUG_ON(addr >= end);
79
80    start = addr;
81    phys_addr -= addr;
82    pgd = pgd_offset_k(addr);
83    do {
84        next = pgd_addr_end(addr, end);
85        err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot);
86        if (err)
87            break;
88    } while (pgd++, addr = next, addr != end);
89
90    flush_cache_vmap(start, end);
91
92    return err;
93}
94EXPORT_SYMBOL_GPL(ioremap_page_range);
95

Archive Download this file



interactive