]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/ixp/npe/IxOsalIoMem.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.git] / cpu / ixp / npe / IxOsalIoMem.c
1 /**
2  * @file IxOsalIoMem.c 
3  *
4  * @brief OS-independent IO/Mem implementation 
5  * 
6  * 
7  * @par
8  * IXP400 SW Release version 2.0
9  * 
10  * -- Copyright Notice --
11  * 
12  * @par
13  * Copyright 2001-2005, Intel Corporation.
14  * All rights reserved.
15  * 
16  * @par
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. Neither the name of the Intel Corporation nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  * 
29  * @par
30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
31  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  * 
42  * @par
43  * -- End of Copyright Notice --
44  */
45
46 /* Access to the global mem map is only allowed in this file */
47 #define IxOsalIoMem_C
48
49 #include "IxOsal.h"
50
51 #define SEARCH_PHYSICAL_ADDRESS (1)
52 #define SEARCH_VIRTUAL_ADDRESS  (2)
53
54 /*
55  * Searches for map using one of the following criteria:
56  * 
57  * - enough room to include a zone starting with the physical "requestedAddress" of size "size" (for mapping)
58  * - includes the virtual "requestedAddress" in its virtual address space (already mapped, for unmapping)
59  * - correct coherency
60  *
61  * Returns a pointer to the map or NULL if a suitable map is not found.
62  */
63 PRIVATE IxOsalMemoryMap *
64 ixOsalMemMapFind (UINT32 requestedAddress,
65     UINT32 size, UINT32 searchCriteria, UINT32 requestedEndianType)
66 {
67     UINT32 mapIndex;
68
69     UINT32 numMapElements =
70         sizeof (ixOsalGlobalMemoryMap) / sizeof (IxOsalMemoryMap);
71
72     for (mapIndex = 0; mapIndex < numMapElements; mapIndex++)
73     {
74         IxOsalMemoryMap *map = &ixOsalGlobalMemoryMap[mapIndex];
75
76         if (searchCriteria == SEARCH_PHYSICAL_ADDRESS
77             && requestedAddress >= map->physicalAddress
78             && (requestedAddress + size) <= (map->physicalAddress + map->size)
79             && (map->mapEndianType & requestedEndianType) != 0)
80         {
81             return map;
82         }
83         else if (searchCriteria == SEARCH_VIRTUAL_ADDRESS
84             && requestedAddress >= map->virtualAddress
85             && requestedAddress <= (map->virtualAddress + map->size)
86             && (map->mapEndianType & requestedEndianType) != 0)
87         {
88             return map;
89         }
90         else if (searchCriteria == SEARCH_PHYSICAL_ADDRESS)
91         {
92             ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
93                 IX_OSAL_LOG_DEV_STDOUT,
94                 "Osal: Checking [phys addr 0x%x:size 0x%x:endianType %d]\n",
95                 map->physicalAddress, map->size, map->mapEndianType, 0, 0, 0);
96         }
97     }
98
99     /*
100      * not found 
101      */
102     return NULL;
103 }
104
105 /*
106  * This function maps an I/O mapped physical memory zone of the given size
107  * into a virtual memory zone accessible by the caller and returns a cookie - 
108  * the start address of the virtual memory zone. 
109  * IX_OSAL_MMAP_PHYS_TO_VIRT should NOT therefore be used on the returned 
110  * virtual address.
111  * The memory zone is to be unmapped using ixOsalMemUnmap once the caller has
112  * finished using this zone (e.g. on driver unload) using the cookie as 
113  * parameter.
114  * The IX_OSAL_READ/WRITE_LONG/SHORT macros should be used to read and write 
115  * the mapped memory, adding the necessary offsets to the address cookie.
116  *
117  * Note: this function is not to be used directly. Use IX_OSAL_MEM_MAP 
118  * instead.
119  */
120 PUBLIC void *
121 ixOsalIoMemMap (UINT32 requestedAddress,
122     UINT32 size, IxOsalMapEndianessType requestedEndianType)
123 {
124     IxOsalMemoryMap *map;
125
126     ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
127         IX_OSAL_LOG_DEV_STDOUT,
128         "OSAL: Mapping [addr 0x%x:size 0x%x:endianType %d]\n",
129         requestedAddress, size, requestedEndianType, 0, 0, 0);
130
131     if (requestedEndianType == IX_OSAL_LE)
132     {
133         ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
134             IX_OSAL_LOG_DEV_STDOUT,
135             "ixOsalIoMemMap: Please specify component coherency mode to use MEM functions \n",
136             0, 0, 0, 0, 0, 0);
137         return (NULL);
138     }
139     map = ixOsalMemMapFind (requestedAddress,
140         size, SEARCH_PHYSICAL_ADDRESS, requestedEndianType);
141     if (map != NULL)
142     {
143         UINT32 offset = requestedAddress - map->physicalAddress;
144
145         ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
146             IX_OSAL_LOG_DEV_STDOUT, "OSAL: Found map [", 0, 0, 0, 0, 0, 0);
147         ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
148             IX_OSAL_LOG_DEV_STDOUT, map->name, 0, 0, 0, 0, 0, 0);
149         ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
150             IX_OSAL_LOG_DEV_STDOUT,
151             ":addr 0x%x: virt 0x%x:size 0x%x:ref %d:endianType %d]\n",
152             map->physicalAddress, map->virtualAddress,
153             map->size, map->refCount, map->mapEndianType, 0);
154
155         if (map->type == IX_OSAL_DYNAMIC_MAP && map->virtualAddress == 0)
156         {
157             if (map->mapFunction != NULL)
158             {
159                 map->mapFunction (map);
160
161                 if (map->virtualAddress == 0)
162                 {
163                     /*
164                      * failed 
165                      */
166                     ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
167                         IX_OSAL_LOG_DEV_STDERR,
168                         "OSAL: Remap failed - [addr 0x%x:size 0x%x:endianType %d]\n",
169                         requestedAddress, size, requestedEndianType, 0, 0, 0);
170                     return NULL;
171                 }
172             }
173             else
174             {
175                 /*
176                  * error, no map function for a dynamic map 
177                  */
178                 ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
179                     IX_OSAL_LOG_DEV_STDERR,
180                     "OSAL: No map function for a dynamic map - "
181                     "[addr 0x%x:size 0x%x:endianType %d]\n",
182                     requestedAddress, size, requestedEndianType, 0, 0, 0);
183
184                 return NULL;
185             }
186         }
187
188         /*
189          * increment reference count 
190          */
191         map->refCount++;
192
193         return (void *) (map->virtualAddress + offset);
194     }
195
196     /*
197      * requested address is not described in the global memory map 
198      */
199     ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
200         IX_OSAL_LOG_DEV_STDERR,
201         "OSAL: No mapping found - [addr 0x%x:size 0x%x:endianType %d]\n",
202         requestedAddress, size, requestedEndianType, 0, 0, 0);
203     return NULL;
204 }
205
206 /*
207  * This function unmaps a previously mapped I/O memory zone using
208  * the cookie obtained in the mapping operation. The memory zone in question
209  * becomes unavailable to the caller once unmapped and the cookie should be
210  * discarded.
211  *
212  * This function cannot fail if the given parameter is correct and does not
213  * return a value.
214  *
215  * Note: this function is not to be used directly. Use IX_OSAL_MEM_UNMAP
216  * instead.
217  */
218 PUBLIC void
219 ixOsalIoMemUnmap (UINT32 requestedAddress, UINT32 endianType)
220 {
221     IxOsalMemoryMap *map;
222
223     if (endianType == IX_OSAL_LE)
224     {
225         ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
226             IX_OSAL_LOG_DEV_STDOUT,
227             "ixOsalIoMemUnmap: Please specify component coherency mode to use MEM functions \n",
228             0, 0, 0, 0, 0, 0);
229         return;
230     }
231
232     if (requestedAddress == 0)
233     {
234         /*
235          * invalid virtual address 
236          */
237         return;
238     }
239
240     map =
241         ixOsalMemMapFind (requestedAddress, 0, SEARCH_VIRTUAL_ADDRESS,
242         endianType);
243
244     if (map != NULL)
245     {
246         if (map->refCount > 0)
247         {
248             /*
249              * decrement reference count 
250              */
251             map->refCount--;
252
253             if (map->refCount == 0)
254             {
255                 /*
256                  * no longer used, deallocate 
257                  */
258                 if (map->type == IX_OSAL_DYNAMIC_MAP
259                     && map->unmapFunction != NULL)
260                 {
261                     map->unmapFunction (map);
262                 }
263             }
264         }
265     }
266     else
267     {
268         ixOsalLog (IX_OSAL_LOG_LVL_WARNING,
269             IX_OSAL_LOG_DEV_STDERR,
270             "OSAL: ixOsServMemUnmap didn't find the requested map "
271             "[virt addr 0x%x: endianType %d], ignoring call\n",
272             requestedAddress, endianType, 0, 0, 0, 0);
273     }
274 }
275
276 /* 
277  * This function Converts a virtual address into a physical 
278  * address, including the dynamically mapped memory.
279  * 
280  * Parameters   virtAddr - virtual address to convert
281  * Return value: corresponding physical address, or NULL 
282  *               if there is no physical address addressable 
283  *               by the given virtual address
284  * OS:  VxWorks, Linux, WinCE, QNX, eCos
285  * Reentrant: Yes
286  * IRQ safe: Yes
287  */
288 PUBLIC UINT32
289 ixOsalIoMemVirtToPhys (UINT32 virtualAddress, UINT32 requestedCoherency)
290 {
291     IxOsalMemoryMap *map =
292         ixOsalMemMapFind (virtualAddress, 0, SEARCH_VIRTUAL_ADDRESS,
293         requestedCoherency);
294
295     if (map != NULL)
296     {
297         return map->physicalAddress + virtualAddress - map->virtualAddress;
298     }
299     else
300     {
301         return (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS (virtualAddress);
302     }
303 }
304
305 /* 
306  * This function Converts a virtual address into a physical 
307  * address, including the dynamically mapped memory.
308  * 
309  * Parameters   virtAddr - virtual address to convert
310  * Return value: corresponding physical address, or NULL 
311  *               if there is no physical address addressable 
312  *               by the given virtual address
313  * OS:  VxWorks, Linux, WinCE, QNX, eCos
314  * Reentrant: Yes
315  * IRQ safe: Yes
316  */
317 PUBLIC UINT32
318 ixOsalIoMemPhysToVirt (UINT32 physicalAddress, UINT32 requestedCoherency)
319 {
320     IxOsalMemoryMap *map =
321         ixOsalMemMapFind (physicalAddress, 0, SEARCH_PHYSICAL_ADDRESS,
322         requestedCoherency);
323
324     if (map != NULL)
325     {
326         return map->virtualAddress + physicalAddress - map->physicalAddress;
327     }
328     else
329     {
330         return (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (physicalAddress);
331     }
332 }