linux/include/linux/io-mapping.h
<<
>>
Prefs
   1/*
   2 * Copyright © 2008 Keith Packard <keithp@keithp.com>
   3 *
   4 * This file is free software; you can redistribute it and/or modify
   5 * it under the terms of version 2 of the GNU General Public License
   6 * as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software Foundation,
  15 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  16 */
  17
  18#ifndef _LINUX_IO_MAPPING_H
  19#define _LINUX_IO_MAPPING_H
  20
  21#include <linux/types.h>
  22#include <linux/slab.h>
  23#include <linux/bug.h>
  24#include <linux/io.h>
  25#include <asm/page.h>
  26
  27/*
  28 * The io_mapping mechanism provides an abstraction for mapping
  29 * individual pages from an io device to the CPU in an efficient fashion.
  30 *
  31 * See Documentation/io-mapping.txt
  32 */
  33
  34#ifdef CONFIG_HAVE_ATOMIC_IOMAP
  35
  36#include <asm/iomap.h>
  37
  38struct io_mapping {
  39        resource_size_t base;
  40        unsigned long size;
  41        pgprot_t prot;
  42};
  43
  44/*
  45 * For small address space machines, mapping large objects
  46 * into the kernel virtual space isn't practical. Where
  47 * available, use fixmap support to dynamically map pages
  48 * of the object at run time.
  49 */
  50
  51static inline struct io_mapping *
  52io_mapping_create_wc(resource_size_t base, unsigned long size)
  53{
  54        struct io_mapping *iomap;
  55        pgprot_t prot;
  56
  57        iomap = kmalloc(sizeof(*iomap), GFP_KERNEL);
  58        if (!iomap)
  59                goto out_err;
  60
  61        if (iomap_create_wc(base, size, &prot))
  62                goto out_free;
  63
  64        iomap->base = base;
  65        iomap->size = size;
  66        iomap->prot = prot;
  67        return iomap;
  68
  69out_free:
  70        kfree(iomap);
  71out_err:
  72        return NULL;
  73}
  74
  75static inline void
  76io_mapping_free(struct io_mapping *mapping)
  77{
  78        iomap_free(mapping->base, mapping->size);
  79        kfree(mapping);
  80}
  81
  82/* Atomic map/unmap */
  83static inline void __iomem *
  84io_mapping_map_atomic_wc(struct io_mapping *mapping,
  85                         unsigned long offset)
  86{
  87        resource_size_t phys_addr;
  88        unsigned long pfn;
  89
  90        BUG_ON(offset >= mapping->size);
  91        phys_addr = mapping->base + offset;
  92        pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
  93        return iomap_atomic_prot_pfn(pfn, mapping->prot);
  94}
  95
  96static inline void
  97io_mapping_unmap_atomic(void __iomem *vaddr)
  98{
  99        iounmap_atomic(vaddr);
 100}
 101
 102static inline void __iomem *
 103io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
 104{
 105        resource_size_t phys_addr;
 106
 107        BUG_ON(offset >= mapping->size);
 108        phys_addr = mapping->base + offset;
 109
 110        return ioremap_wc(phys_addr, PAGE_SIZE);
 111}
 112
 113static inline void
 114io_mapping_unmap(void __iomem *vaddr)
 115{
 116        iounmap(vaddr);
 117}
 118
 119#else
 120
 121#include <linux/uaccess.h>
 122
 123/* this struct isn't actually defined anywhere */
 124struct io_mapping;
 125
 126/* Create the io_mapping object*/
 127static inline struct io_mapping *
 128io_mapping_create_wc(resource_size_t base, unsigned long size)
 129{
 130        return (struct io_mapping __force *) ioremap_wc(base, size);
 131}
 132
 133static inline void
 134io_mapping_free(struct io_mapping *mapping)
 135{
 136        iounmap((void __force __iomem *) mapping);
 137}
 138
 139/* Atomic map/unmap */
 140static inline void __iomem *
 141io_mapping_map_atomic_wc(struct io_mapping *mapping,
 142                         unsigned long offset)
 143{
 144        preempt_disable();
 145        pagefault_disable();
 146        return ((char __force __iomem *) mapping) + offset;
 147}
 148
 149static inline void
 150io_mapping_unmap_atomic(void __iomem *vaddr)
 151{
 152        pagefault_enable();
 153        preempt_enable();
 154}
 155
 156/* Non-atomic map/unmap */
 157static inline void __iomem *
 158io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
 159{
 160        return ((char __force __iomem *) mapping) + offset;
 161}
 162
 163static inline void
 164io_mapping_unmap(void __iomem *vaddr)
 165{
 166}
 167
 168#endif /* HAVE_ATOMIC_IOMAP */
 169
 170#endif /* _LINUX_IO_MAPPING_H */
 171