Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ioremap.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Portions Copyright (C) Cisco Systems, Inc.
8  */
9 #ifndef __ASM_MACH_POWERTV_IOREMAP_H
10 #define __ASM_MACH_POWERTV_IOREMAP_H
11 
12 #include <linux/types.h>
13 #include <linux/log2.h>
14 #include <linux/compiler.h>
15 
16 #include <asm/pgtable-bits.h>
17 #include <asm/addrspace.h>
18 
19 /* We're going to mess with bits, so get sizes */
20 #define IOR_BPC 8 /* Bits per char */
21 #define IOR_PHYS_BITS (IOR_BPC * sizeof(phys_addr_t))
22 #define IOR_DMA_BITS (IOR_BPC * sizeof(dma_addr_t))
23 
24 /*
25  * Define the granularity of physical/DMA mapping in terms of the number
26  * of bits that defines the offset within a grain. These will be the
27  * least significant bits of the address. The rest of a physical or DMA
28  * address will be used to index into an appropriate table to find the
29  * offset to add to the address to yield the corresponding DMA or physical
30  * address, respectively.
31  */
32 #define IOR_LSBITS 22 /* Bits in a grain */
33 
34 /*
35  * Compute the number of most significant address bits after removing those
36  * used for the offset within a grain and then compute the number of table
37  * entries for the conversion.
38  */
39 #define IOR_PHYS_MSBITS (IOR_PHYS_BITS - IOR_LSBITS)
40 #define IOR_NUM_PHYS_TO_DMA ((phys_addr_t) 1 << IOR_PHYS_MSBITS)
41 
42 #define IOR_DMA_MSBITS (IOR_DMA_BITS - IOR_LSBITS)
43 #define IOR_NUM_DMA_TO_PHYS ((dma_addr_t) 1 << IOR_DMA_MSBITS)
44 
45 /*
46  * Define data structures used as elements in the arrays for the conversion
47  * between physical and DMA addresses. We do some slightly fancy math to
48  * compute the width of the offset element of the conversion tables so
49  * that we can have the smallest conversion tables. Next, round up the
50  * sizes to the next higher power of two, i.e. the offset element will have
51  * 8, 16, 32, 64, etc. bits. This eliminates the need to mask off any
52  * bits. Finally, we compute a shift value that puts the most significant
53  * bits of the offset into the most significant bits of the offset element.
54  * This makes it more efficient on processors without barrel shifters and
55  * easier to see the values if the conversion table is dumped in binary.
56  */
57 #define _IOR_OFFSET_WIDTH(n) (1 << order_base_2(n))
58 #define IOR_OFFSET_WIDTH(n) \
59  (_IOR_OFFSET_WIDTH(n) < 8 ? 8 : _IOR_OFFSET_WIDTH(n))
60 
61 #define IOR_PHYS_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_PHYS_MSBITS)
62 #define IOR_PHYS_SHIFT (IOR_PHYS_BITS - IOR_PHYS_OFFSET_BITS)
63 
64 #define IOR_DMA_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_DMA_MSBITS)
65 #define IOR_DMA_SHIFT (IOR_DMA_BITS - IOR_DMA_OFFSET_BITS)
66 
70 };
71 
75 };
76 
79 
80 static inline dma_addr_t _phys_to_dma_offset_raw(phys_addr_t phys)
81 {
82  return (dma_addr_t)_ior_phys_to_dma[phys >> IOR_LSBITS].offset;
83 }
84 
85 static inline dma_addr_t _dma_to_phys_offset_raw(dma_addr_t dma)
86 {
87  return (dma_addr_t)_ior_dma_to_phys[dma >> IOR_LSBITS].offset;
88 }
89 
90 /* These are not portable and should not be used in drivers. Drivers should
91  * be using ioremap() and friends to map physical addresses to virtual
92  * addresses and dma_map*() and friends to map virtual addresses into DMA
93  * addresses and back.
94  */
95 static inline dma_addr_t phys_to_dma(phys_addr_t phys)
96 {
97  return phys + (_phys_to_dma_offset_raw(phys) << IOR_PHYS_SHIFT);
98 }
99 
100 static inline phys_addr_t dma_to_phys(dma_addr_t dma)
101 {
102  return dma + (_dma_to_phys_offset_raw(dma) << IOR_DMA_SHIFT);
103 }
104 
105 extern void ioremap_add_map(dma_addr_t phys, phys_addr_t alias,
106  dma_addr_t size);
107 
108 /*
109  * Allow physical addresses to be fixed up to help peripherals located
110  * outside the low 32-bit range -- generic pass-through version.
111  */
112 static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
113 {
114  return phys_addr;
115 }
116 
117 /*
118  * Handle the special case of addresses the area aliased into the first
119  * 512 MiB of the processor's physical address space. These turn into either
120  * kseg0 or kseg1 addresses, depending on flags.
121  */
122 static inline void __iomem *plat_ioremap(phys_t start, unsigned long size,
123  unsigned long flags)
124 {
126  void __iomem *result = NULL;
127 
128  /* Start by checking to see whether this is an aliased address */
129  start_offset = _dma_to_phys_offset_raw(start);
130 
131  /*
132  * If:
133  * o the memory is aliased into the first 512 MiB, and
134  * o the start and end are in the same RAM bank, and
135  * o we don't have a zero size or wrap around, and
136  * o we are supposed to create an uncached mapping,
137  * handle this is a kseg0 or kseg1 address
138  */
139  if (start_offset != 0) {
141  dma_addr_t dma_to_phys_offset;
142 
143  last = start + size - 1;
144  dma_to_phys_offset =
145  _dma_to_phys_offset_raw(last) << IOR_DMA_SHIFT;
146 
147  if (dma_to_phys_offset == start_offset &&
148  size != 0 && start <= last) {
149  phys_t adjusted_start;
150  adjusted_start = start + start_offset;
151  if (flags == _CACHE_UNCACHED)
152  result = (void __iomem *) (unsigned long)
153  CKSEG1ADDR(adjusted_start);
154  else
155  result = (void __iomem *) (unsigned long)
156  CKSEG0ADDR(adjusted_start);
157  }
158  }
159 
160  return result;
161 }
162 
163 static inline int plat_iounmap(const volatile void __iomem *addr)
164 {
165  return 0;
166 }
167 #endif /* __ASM_MACH_POWERTV_IOREMAP_H */