linux/arch/mips/powertv/ioremap.c
<<
>>
Prefs
   1/*
   2 *                      ioremap.c
   3 *
   4 * Support for mapping between dma_addr_t values a phys_addr_t values.
   5 *
   6 * Copyright (C) 2005-2009 Scientific-Atlanta, Inc.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  21 *
  22 * Author:       David VomLehn <dvomlehn@cisco.com>
  23 *
  24 * Description:  Defines the platform resources for the SA settop.
  25 *
  26 * NOTE: The bootloader allocates persistent memory at an address which is
  27 * 16 MiB below the end of the highest address in KSEG0. All fixed
  28 * address memory reservations must avoid this region.
  29 */
  30
  31#include <linux/kernel.h>
  32#include <linux/module.h>
  33
  34#include <asm/mach-powertv/ioremap.h>
  35
  36/*
  37 * Define the sizes of and masks for grains in physical and DMA space. The
  38 * values are the same but the types are not.
  39 */
  40#define IOR_PHYS_GRAIN          ((phys_addr_t) 1 << IOR_LSBITS)
  41#define IOR_PHYS_GRAIN_MASK     (IOR_PHYS_GRAIN - 1)
  42
  43#define IOR_DMA_GRAIN           ((dma_addr_t) 1 << IOR_LSBITS)
  44#define IOR_DMA_GRAIN_MASK      (IOR_DMA_GRAIN - 1)
  45
  46/*
  47 * Values that, when accessed by an index derived from a phys_addr_t and
  48 * added to phys_addr_t value, yield a DMA address
  49 */
  50struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
  51EXPORT_SYMBOL(_ior_phys_to_dma);
  52
  53/*
  54 * Values that, when accessed by an index derived from a dma_addr_t and
  55 * added to that dma_addr_t value, yield a physical address
  56 */
  57struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];
  58EXPORT_SYMBOL(_ior_dma_to_phys);
  59
  60/**
  61 * setup_dma_to_phys - set up conversion from DMA to physical addresses
  62 * @dma_idx:    Top IOR_LSBITS bits of the DMA address, i.e. an index
  63 *              into the array _dma_to_phys.
  64 * @delta:      Value that, when added to the DMA address, will yield the
  65 *              physical address
  66 * @s:          Number of bytes in the section of memory with the given delta
  67 *              between DMA and physical addresses.
  68 */
  69static void setup_dma_to_phys(dma_addr_t dma, phys_addr_t delta, dma_addr_t s)
  70{
  71        int dma_idx, first_idx, last_idx;
  72        phys_addr_t first, last;
  73
  74        /*
  75         * Calculate the first and last indices, rounding the first up and
  76         * the second down.
  77         */
  78        first = dma & ~IOR_DMA_GRAIN_MASK;
  79        last = (dma + s - 1) & ~IOR_DMA_GRAIN_MASK;
  80        first_idx = first >> IOR_LSBITS;                /* Convert to indices */
  81        last_idx = last >> IOR_LSBITS;
  82
  83        for (dma_idx = first_idx; dma_idx <= last_idx; dma_idx++)
  84                _ior_dma_to_phys[dma_idx].offset = delta >> IOR_DMA_SHIFT;
  85}
  86
  87/**
  88 * setup_phys_to_dma - set up conversion from DMA to physical addresses
  89 * @phys_idx:   Top IOR_LSBITS bits of the DMA address, i.e. an index
  90 *              into the array _phys_to_dma.
  91 * @delta:      Value that, when added to the DMA address, will yield the
  92 *              physical address
  93 * @s:          Number of bytes in the section of memory with the given delta
  94 *              between DMA and physical addresses.
  95 */
  96static void setup_phys_to_dma(phys_addr_t phys, dma_addr_t delta, phys_addr_t s)
  97{
  98        int phys_idx, first_idx, last_idx;
  99        phys_addr_t first, last;
 100
 101        /*
 102         * Calculate the first and last indices, rounding the first up and
 103         * the second down.
 104         */
 105        first = phys & ~IOR_PHYS_GRAIN_MASK;
 106        last = (phys + s - 1) & ~IOR_PHYS_GRAIN_MASK;
 107        first_idx = first >> IOR_LSBITS;                /* Convert to indices */
 108        last_idx = last >> IOR_LSBITS;
 109
 110        for (phys_idx = first_idx; phys_idx <= last_idx; phys_idx++)
 111                _ior_phys_to_dma[phys_idx].offset = delta >> IOR_PHYS_SHIFT;
 112}
 113
 114/**
 115 * ioremap_add_map - add to the physical and DMA address conversion arrays
 116 * @phys:       Process's view of the address of the start of the memory chunk
 117 * @dma:        DMA address of the start of the memory chunk
 118 * @size:       Size, in bytes, of the chunk of memory
 119 *
 120 * NOTE: It might be obvious, but the assumption is that all @size bytes have
 121 * the same offset between the physical address and the DMA address.
 122 */
 123void ioremap_add_map(phys_addr_t phys, phys_addr_t dma, phys_addr_t size)
 124{
 125        if (size == 0)
 126                return;
 127
 128        if ((dma & IOR_DMA_GRAIN_MASK) != 0 ||
 129                (phys & IOR_PHYS_GRAIN_MASK) != 0 ||
 130                (size & IOR_PHYS_GRAIN_MASK) != 0)
 131                pr_crit("Memory allocation must be in chunks of 0x%x bytes\n",
 132                        IOR_PHYS_GRAIN);
 133
 134        setup_dma_to_phys(dma, phys - dma, size);
 135        setup_phys_to_dma(phys, dma - phys, size);
 136}
 137