]>
Commit | Line | Data |
---|---|---|
1394f032 | 1 | /* |
5e95320f | 2 | * File: arch/blackfin/mm/sram-alloc.c |
1394f032 BW |
3 | * Based on: |
4 | * Author: | |
5 | * | |
6 | * Created: | |
5e95320f | 7 | * Description: SRAM allocator for Blackfin L1 and L2 memory |
1394f032 BW |
8 | * |
9 | * Modified: | |
5e95320f | 10 | * Copyright 2004-2008 Analog Devices Inc. |
1394f032 BW |
11 | * |
12 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify | |
15 | * it under the terms of the GNU General Public License as published by | |
16 | * the Free Software Foundation; either version 2 of the License, or | |
17 | * (at your option) any later version. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, | |
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
22 | * GNU General Public License for more details. | |
23 | * | |
24 | * You should have received a copy of the GNU General Public License | |
25 | * along with this program; if not, see the file COPYING, or write | |
26 | * to the Free Software Foundation, Inc., | |
27 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
28 | */ | |
29 | ||
1394f032 BW |
30 | #include <linux/module.h> |
31 | #include <linux/kernel.h> | |
32 | #include <linux/types.h> | |
33 | #include <linux/miscdevice.h> | |
34 | #include <linux/ioport.h> | |
35 | #include <linux/fcntl.h> | |
36 | #include <linux/init.h> | |
37 | #include <linux/poll.h> | |
38 | #include <linux/proc_fs.h> | |
39 | #include <linux/spinlock.h> | |
40 | #include <linux/rtc.h> | |
41 | #include <asm/blackfin.h> | |
42 | #include "blackfin_sram.h" | |
43 | ||
5d481f49 | 44 | static spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock; |
262c3825 | 45 | static spinlock_t l2_sram_lock; |
1394f032 BW |
46 | |
47 | /* the data structure for L1 scratchpad and DATA SRAM */ | |
5d481f49 | 48 | struct sram_piece { |
1394f032 BW |
49 | void *paddr; |
50 | int size; | |
bc61b4e6 | 51 | pid_t pid; |
5d481f49 | 52 | struct sram_piece *next; |
1394f032 BW |
53 | }; |
54 | ||
5d481f49 | 55 | static struct sram_piece free_l1_ssram_head, used_l1_ssram_head; |
1394f032 BW |
56 | |
57 | #if L1_DATA_A_LENGTH != 0 | |
5d481f49 | 58 | static struct sram_piece free_l1_data_A_sram_head, used_l1_data_A_sram_head; |
1394f032 BW |
59 | #endif |
60 | ||
61 | #if L1_DATA_B_LENGTH != 0 | |
5d481f49 | 62 | static struct sram_piece free_l1_data_B_sram_head, used_l1_data_B_sram_head; |
1394f032 BW |
63 | #endif |
64 | ||
65 | #if L1_CODE_LENGTH != 0 | |
5d481f49 | 66 | static struct sram_piece free_l1_inst_sram_head, used_l1_inst_sram_head; |
1394f032 BW |
67 | #endif |
68 | ||
07aa7be5 | 69 | #if L2_LENGTH != 0 |
262c3825 SZ |
70 | static struct sram_piece free_l2_sram_head, used_l2_sram_head; |
71 | #endif | |
72 | ||
5d481f49 SZ |
73 | static struct kmem_cache *sram_piece_cache; |
74 | ||
1394f032 | 75 | /* L1 Scratchpad SRAM initialization function */ |
5d481f49 | 76 | static void __init l1sram_init(void) |
1394f032 | 77 | { |
5d481f49 SZ |
78 | free_l1_ssram_head.next = |
79 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
80 | if (!free_l1_ssram_head.next) { | |
5e95320f | 81 | printk(KERN_INFO "Failed to initialize Scratchpad data SRAM\n"); |
5d481f49 SZ |
82 | return; |
83 | } | |
1394f032 | 84 | |
5d481f49 SZ |
85 | free_l1_ssram_head.next->paddr = (void *)L1_SCRATCH_START; |
86 | free_l1_ssram_head.next->size = L1_SCRATCH_LENGTH; | |
87 | free_l1_ssram_head.next->pid = 0; | |
88 | free_l1_ssram_head.next->next = NULL; | |
89 | ||
90 | used_l1_ssram_head.next = NULL; | |
1394f032 BW |
91 | |
92 | /* mutex initialize */ | |
93 | spin_lock_init(&l1sram_lock); | |
5d481f49 SZ |
94 | |
95 | printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n", | |
96 | L1_SCRATCH_LENGTH >> 10); | |
1394f032 BW |
97 | } |
98 | ||
5d481f49 | 99 | static void __init l1_data_sram_init(void) |
1394f032 BW |
100 | { |
101 | #if L1_DATA_A_LENGTH != 0 | |
5d481f49 SZ |
102 | free_l1_data_A_sram_head.next = |
103 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
104 | if (!free_l1_data_A_sram_head.next) { | |
5e95320f | 105 | printk(KERN_INFO "Failed to initialize L1 Data A SRAM\n"); |
5d481f49 SZ |
106 | return; |
107 | } | |
108 | ||
109 | free_l1_data_A_sram_head.next->paddr = | |
110 | (void *)L1_DATA_A_START + (_ebss_l1 - _sdata_l1); | |
111 | free_l1_data_A_sram_head.next->size = | |
112 | L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1); | |
113 | free_l1_data_A_sram_head.next->pid = 0; | |
114 | free_l1_data_A_sram_head.next->next = NULL; | |
115 | ||
116 | used_l1_data_A_sram_head.next = NULL; | |
bc61b4e6 | 117 | |
262c3825 | 118 | printk(KERN_INFO "Blackfin L1 Data A SRAM: %d KB (%d KB free)\n", |
5d481f49 SZ |
119 | L1_DATA_A_LENGTH >> 10, |
120 | free_l1_data_A_sram_head.next->size >> 10); | |
1394f032 BW |
121 | #endif |
122 | #if L1_DATA_B_LENGTH != 0 | |
5d481f49 SZ |
123 | free_l1_data_B_sram_head.next = |
124 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
125 | if (!free_l1_data_B_sram_head.next) { | |
5e95320f | 126 | printk(KERN_INFO "Failed to initialize L1 Data B SRAM\n"); |
5d481f49 SZ |
127 | return; |
128 | } | |
129 | ||
130 | free_l1_data_B_sram_head.next->paddr = | |
131 | (void *)L1_DATA_B_START + (_ebss_b_l1 - _sdata_b_l1); | |
132 | free_l1_data_B_sram_head.next->size = | |
133 | L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1); | |
134 | free_l1_data_B_sram_head.next->pid = 0; | |
135 | free_l1_data_B_sram_head.next->next = NULL; | |
136 | ||
137 | used_l1_data_B_sram_head.next = NULL; | |
bc61b4e6 | 138 | |
262c3825 | 139 | printk(KERN_INFO "Blackfin L1 Data B SRAM: %d KB (%d KB free)\n", |
5d481f49 SZ |
140 | L1_DATA_B_LENGTH >> 10, |
141 | free_l1_data_B_sram_head.next->size >> 10); | |
1394f032 BW |
142 | #endif |
143 | ||
144 | /* mutex initialize */ | |
145 | spin_lock_init(&l1_data_sram_lock); | |
146 | } | |
147 | ||
5d481f49 | 148 | static void __init l1_inst_sram_init(void) |
1394f032 BW |
149 | { |
150 | #if L1_CODE_LENGTH != 0 | |
5d481f49 SZ |
151 | free_l1_inst_sram_head.next = |
152 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
153 | if (!free_l1_inst_sram_head.next) { | |
5e95320f | 154 | printk(KERN_INFO "Failed to initialize L1 Instruction SRAM\n"); |
5d481f49 SZ |
155 | return; |
156 | } | |
157 | ||
158 | free_l1_inst_sram_head.next->paddr = | |
159 | (void *)L1_CODE_START + (_etext_l1 - _stext_l1); | |
160 | free_l1_inst_sram_head.next->size = | |
161 | L1_CODE_LENGTH - (_etext_l1 - _stext_l1); | |
162 | free_l1_inst_sram_head.next->pid = 0; | |
163 | free_l1_inst_sram_head.next->next = NULL; | |
164 | ||
165 | used_l1_inst_sram_head.next = NULL; | |
bc61b4e6 | 166 | |
262c3825 | 167 | printk(KERN_INFO "Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n", |
5d481f49 SZ |
168 | L1_CODE_LENGTH >> 10, |
169 | free_l1_inst_sram_head.next->size >> 10); | |
1394f032 BW |
170 | #endif |
171 | ||
172 | /* mutex initialize */ | |
173 | spin_lock_init(&l1_inst_sram_lock); | |
174 | } | |
175 | ||
262c3825 SZ |
176 | static void __init l2_sram_init(void) |
177 | { | |
07aa7be5 | 178 | #if L2_LENGTH != 0 |
262c3825 SZ |
179 | free_l2_sram_head.next = |
180 | kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
181 | if (!free_l2_sram_head.next) { | |
5e95320f | 182 | printk(KERN_INFO "Failed to initialize L2 SRAM\n"); |
262c3825 SZ |
183 | return; |
184 | } | |
185 | ||
b2c2f303 JZ |
186 | free_l2_sram_head.next->paddr = |
187 | (void *)L2_START + (_ebss_l2 - _stext_l2); | |
188 | free_l2_sram_head.next->size = | |
189 | L2_LENGTH - (_ebss_l2 - _stext_l2); | |
262c3825 SZ |
190 | free_l2_sram_head.next->pid = 0; |
191 | free_l2_sram_head.next->next = NULL; | |
192 | ||
193 | used_l2_sram_head.next = NULL; | |
194 | ||
195 | printk(KERN_INFO "Blackfin L2 SRAM: %d KB (%d KB free)\n", | |
196 | L2_LENGTH >> 10, | |
197 | free_l2_sram_head.next->size >> 10); | |
198 | #endif | |
199 | ||
200 | /* mutex initialize */ | |
201 | spin_lock_init(&l2_sram_lock); | |
202 | } | |
5d481f49 SZ |
203 | void __init bfin_sram_init(void) |
204 | { | |
205 | sram_piece_cache = kmem_cache_create("sram_piece_cache", | |
206 | sizeof(struct sram_piece), | |
207 | 0, SLAB_PANIC, NULL); | |
208 | ||
209 | l1sram_init(); | |
210 | l1_data_sram_init(); | |
211 | l1_inst_sram_init(); | |
262c3825 | 212 | l2_sram_init(); |
5d481f49 SZ |
213 | } |
214 | ||
262c3825 SZ |
215 | /* SRAM allocate function */ |
216 | static void *_sram_alloc(size_t size, struct sram_piece *pfree_head, | |
5d481f49 | 217 | struct sram_piece *pused_head) |
1394f032 | 218 | { |
5d481f49 | 219 | struct sram_piece *pslot, *plast, *pavail; |
1394f032 | 220 | |
5d481f49 | 221 | if (size <= 0 || !pfree_head || !pused_head) |
1394f032 BW |
222 | return NULL; |
223 | ||
224 | /* Align the size */ | |
225 | size = (size + 3) & ~3; | |
226 | ||
5d481f49 SZ |
227 | pslot = pfree_head->next; |
228 | plast = pfree_head; | |
229 | ||
230 | /* search an available piece slot */ | |
231 | while (pslot != NULL && size > pslot->size) { | |
232 | plast = pslot; | |
233 | pslot = pslot->next; | |
1394f032 | 234 | } |
5d481f49 SZ |
235 | |
236 | if (!pslot) | |
1394f032 BW |
237 | return NULL; |
238 | ||
5d481f49 SZ |
239 | if (pslot->size == size) { |
240 | plast->next = pslot->next; | |
241 | pavail = pslot; | |
242 | } else { | |
243 | pavail = kmem_cache_alloc(sram_piece_cache, GFP_KERNEL); | |
244 | ||
245 | if (!pavail) | |
246 | return NULL; | |
247 | ||
248 | pavail->paddr = pslot->paddr; | |
249 | pavail->size = size; | |
250 | pslot->paddr += size; | |
251 | pslot->size -= size; | |
1394f032 BW |
252 | } |
253 | ||
5d481f49 SZ |
254 | pavail->pid = current->pid; |
255 | ||
256 | pslot = pused_head->next; | |
257 | plast = pused_head; | |
258 | ||
259 | /* insert new piece into used piece list !!! */ | |
260 | while (pslot != NULL && pavail->paddr < pslot->paddr) { | |
261 | plast = pslot; | |
262 | pslot = pslot->next; | |
263 | } | |
264 | ||
265 | pavail->next = pslot; | |
266 | plast->next = pavail; | |
267 | ||
268 | return pavail->paddr; | |
1394f032 BW |
269 | } |
270 | ||
271 | /* Allocate the largest available block. */ | |
262c3825 | 272 | static void *_sram_alloc_max(struct sram_piece *pfree_head, |
5d481f49 | 273 | struct sram_piece *pused_head, |
1394f032 BW |
274 | unsigned long *psize) |
275 | { | |
5d481f49 SZ |
276 | struct sram_piece *pslot, *pmax; |
277 | ||
278 | if (!pfree_head || !pused_head) | |
279 | return NULL; | |
280 | ||
281 | pmax = pslot = pfree_head->next; | |
1394f032 | 282 | |
5d481f49 SZ |
283 | /* search an available piece slot */ |
284 | while (pslot != NULL) { | |
285 | if (pslot->size > pmax->size) | |
286 | pmax = pslot; | |
287 | pslot = pslot->next; | |
1394f032 | 288 | } |
5d481f49 SZ |
289 | |
290 | if (!pmax) | |
1394f032 | 291 | return NULL; |
1394f032 | 292 | |
5d481f49 SZ |
293 | *psize = pmax->size; |
294 | ||
262c3825 | 295 | return _sram_alloc(*psize, pfree_head, pused_head); |
1394f032 BW |
296 | } |
297 | ||
262c3825 SZ |
298 | /* SRAM free function */ |
299 | static int _sram_free(const void *addr, | |
5d481f49 SZ |
300 | struct sram_piece *pfree_head, |
301 | struct sram_piece *pused_head) | |
1394f032 | 302 | { |
5d481f49 SZ |
303 | struct sram_piece *pslot, *plast, *pavail; |
304 | ||
305 | if (!pfree_head || !pused_head) | |
306 | return -1; | |
1394f032 BW |
307 | |
308 | /* search the relevant memory slot */ | |
5d481f49 SZ |
309 | pslot = pused_head->next; |
310 | plast = pused_head; | |
311 | ||
312 | /* search an available piece slot */ | |
313 | while (pslot != NULL && pslot->paddr != addr) { | |
314 | plast = pslot; | |
315 | pslot = pslot->next; | |
1394f032 | 316 | } |
5d481f49 SZ |
317 | |
318 | if (!pslot) | |
1394f032 BW |
319 | return -1; |
320 | ||
5d481f49 SZ |
321 | plast->next = pslot->next; |
322 | pavail = pslot; | |
323 | pavail->pid = 0; | |
324 | ||
325 | /* insert free pieces back to the free list */ | |
326 | pslot = pfree_head->next; | |
327 | plast = pfree_head; | |
328 | ||
329 | while (pslot != NULL && addr > pslot->paddr) { | |
330 | plast = pslot; | |
331 | pslot = pslot->next; | |
332 | } | |
333 | ||
334 | if (plast != pfree_head && plast->paddr + plast->size == pavail->paddr) { | |
335 | plast->size += pavail->size; | |
336 | kmem_cache_free(sram_piece_cache, pavail); | |
337 | } else { | |
225f7e1e | 338 | pavail->next = plast->next; |
5d481f49 SZ |
339 | plast->next = pavail; |
340 | plast = pavail; | |
1394f032 BW |
341 | } |
342 | ||
5d481f49 SZ |
343 | if (pslot && plast->paddr + plast->size == pslot->paddr) { |
344 | plast->size += pslot->size; | |
345 | plast->next = pslot->next; | |
346 | kmem_cache_free(sram_piece_cache, pslot); | |
1394f032 BW |
347 | } |
348 | ||
349 | return 0; | |
350 | } | |
351 | ||
352 | int sram_free(const void *addr) | |
353 | { | |
5e95320f | 354 | |
1394f032 | 355 | #if L1_CODE_LENGTH != 0 |
5e95320f | 356 | if (addr >= (void *)L1_CODE_START |
1394f032 BW |
357 | && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH)) |
358 | return l1_inst_sram_free(addr); | |
5e95320f | 359 | else |
1394f032 BW |
360 | #endif |
361 | #if L1_DATA_A_LENGTH != 0 | |
5e95320f | 362 | if (addr >= (void *)L1_DATA_A_START |
1394f032 BW |
363 | && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH)) |
364 | return l1_data_A_sram_free(addr); | |
5e95320f | 365 | else |
1394f032 BW |
366 | #endif |
367 | #if L1_DATA_B_LENGTH != 0 | |
5e95320f | 368 | if (addr >= (void *)L1_DATA_B_START |
1394f032 BW |
369 | && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH)) |
370 | return l1_data_B_sram_free(addr); | |
5e95320f | 371 | else |
262c3825 | 372 | #endif |
07aa7be5 | 373 | #if L2_LENGTH != 0 |
5e95320f | 374 | if (addr >= (void *)L2_START |
262c3825 SZ |
375 | && addr < (void *)(L2_START + L2_LENGTH)) |
376 | return l2_sram_free(addr); | |
1394f032 | 377 | else |
5e95320f | 378 | #endif |
1394f032 BW |
379 | return -1; |
380 | } | |
381 | EXPORT_SYMBOL(sram_free); | |
382 | ||
383 | void *l1_data_A_sram_alloc(size_t size) | |
384 | { | |
226a6ec3 | 385 | unsigned long flags; |
1394f032 BW |
386 | void *addr = NULL; |
387 | ||
388 | /* add mutex operation */ | |
389 | spin_lock_irqsave(&l1_data_sram_lock, flags); | |
390 | ||
391 | #if L1_DATA_A_LENGTH != 0 | |
262c3825 | 392 | addr = _sram_alloc(size, &free_l1_data_A_sram_head, |
5d481f49 | 393 | &used_l1_data_A_sram_head); |
1394f032 BW |
394 | #endif |
395 | ||
396 | /* add mutex operation */ | |
397 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | |
398 | ||
399 | pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n", | |
400 | (long unsigned int)addr, size); | |
401 | ||
402 | return addr; | |
403 | } | |
404 | EXPORT_SYMBOL(l1_data_A_sram_alloc); | |
405 | ||
406 | int l1_data_A_sram_free(const void *addr) | |
407 | { | |
226a6ec3 | 408 | unsigned long flags; |
1394f032 BW |
409 | int ret; |
410 | ||
411 | /* add mutex operation */ | |
412 | spin_lock_irqsave(&l1_data_sram_lock, flags); | |
413 | ||
414 | #if L1_DATA_A_LENGTH != 0 | |
262c3825 | 415 | ret = _sram_free(addr, &free_l1_data_A_sram_head, |
5d481f49 | 416 | &used_l1_data_A_sram_head); |
1394f032 BW |
417 | #else |
418 | ret = -1; | |
419 | #endif | |
420 | ||
421 | /* add mutex operation */ | |
422 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | |
423 | ||
424 | return ret; | |
425 | } | |
426 | EXPORT_SYMBOL(l1_data_A_sram_free); | |
427 | ||
428 | void *l1_data_B_sram_alloc(size_t size) | |
429 | { | |
430 | #if L1_DATA_B_LENGTH != 0 | |
226a6ec3 | 431 | unsigned long flags; |
1394f032 BW |
432 | void *addr; |
433 | ||
434 | /* add mutex operation */ | |
435 | spin_lock_irqsave(&l1_data_sram_lock, flags); | |
436 | ||
262c3825 | 437 | addr = _sram_alloc(size, &free_l1_data_B_sram_head, |
5d481f49 | 438 | &used_l1_data_B_sram_head); |
1394f032 BW |
439 | |
440 | /* add mutex operation */ | |
441 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | |
442 | ||
443 | pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n", | |
444 | (long unsigned int)addr, size); | |
445 | ||
446 | return addr; | |
447 | #else | |
448 | return NULL; | |
449 | #endif | |
450 | } | |
451 | EXPORT_SYMBOL(l1_data_B_sram_alloc); | |
452 | ||
453 | int l1_data_B_sram_free(const void *addr) | |
454 | { | |
455 | #if L1_DATA_B_LENGTH != 0 | |
226a6ec3 | 456 | unsigned long flags; |
1394f032 BW |
457 | int ret; |
458 | ||
459 | /* add mutex operation */ | |
460 | spin_lock_irqsave(&l1_data_sram_lock, flags); | |
461 | ||
262c3825 | 462 | ret = _sram_free(addr, &free_l1_data_B_sram_head, |
5d481f49 | 463 | &used_l1_data_B_sram_head); |
1394f032 BW |
464 | |
465 | /* add mutex operation */ | |
466 | spin_unlock_irqrestore(&l1_data_sram_lock, flags); | |
467 | ||
468 | return ret; | |
469 | #else | |
470 | return -1; | |
471 | #endif | |
472 | } | |
473 | EXPORT_SYMBOL(l1_data_B_sram_free); | |
474 | ||
475 | void *l1_data_sram_alloc(size_t size) | |
476 | { | |
477 | void *addr = l1_data_A_sram_alloc(size); | |
478 | ||
479 | if (!addr) | |
480 | addr = l1_data_B_sram_alloc(size); | |
481 | ||
482 | return addr; | |
483 | } | |
484 | EXPORT_SYMBOL(l1_data_sram_alloc); | |
485 | ||
486 | void *l1_data_sram_zalloc(size_t size) | |
487 | { | |
488 | void *addr = l1_data_sram_alloc(size); | |
489 | ||
490 | if (addr) | |
491 | memset(addr, 0x00, size); | |
492 | ||
493 | return addr; | |
494 | } | |
495 | EXPORT_SYMBOL(l1_data_sram_zalloc); | |
496 | ||
497 | int l1_data_sram_free(const void *addr) | |
498 | { | |
499 | int ret; | |
500 | ret = l1_data_A_sram_free(addr); | |
501 | if (ret == -1) | |
502 | ret = l1_data_B_sram_free(addr); | |
503 | return ret; | |
504 | } | |
505 | EXPORT_SYMBOL(l1_data_sram_free); | |
506 | ||
507 | void *l1_inst_sram_alloc(size_t size) | |
508 | { | |
c5b50df8 | 509 | #if L1_CODE_LENGTH != 0 |
226a6ec3 | 510 | unsigned long flags; |
1394f032 BW |
511 | void *addr; |
512 | ||
513 | /* add mutex operation */ | |
514 | spin_lock_irqsave(&l1_inst_sram_lock, flags); | |
515 | ||
262c3825 | 516 | addr = _sram_alloc(size, &free_l1_inst_sram_head, |
5d481f49 | 517 | &used_l1_inst_sram_head); |
1394f032 BW |
518 | |
519 | /* add mutex operation */ | |
520 | spin_unlock_irqrestore(&l1_inst_sram_lock, flags); | |
521 | ||
522 | pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n", | |
523 | (long unsigned int)addr, size); | |
524 | ||
525 | return addr; | |
526 | #else | |
527 | return NULL; | |
528 | #endif | |
529 | } | |
530 | EXPORT_SYMBOL(l1_inst_sram_alloc); | |
531 | ||
532 | int l1_inst_sram_free(const void *addr) | |
533 | { | |
534 | #if L1_CODE_LENGTH != 0 | |
226a6ec3 | 535 | unsigned long flags; |
1394f032 BW |
536 | int ret; |
537 | ||
538 | /* add mutex operation */ | |
539 | spin_lock_irqsave(&l1_inst_sram_lock, flags); | |
540 | ||
262c3825 | 541 | ret = _sram_free(addr, &free_l1_inst_sram_head, |
5d481f49 | 542 | &used_l1_inst_sram_head); |
1394f032 BW |
543 | |
544 | /* add mutex operation */ | |
545 | spin_unlock_irqrestore(&l1_inst_sram_lock, flags); | |
546 | ||
547 | return ret; | |
548 | #else | |
549 | return -1; | |
550 | #endif | |
551 | } | |
552 | EXPORT_SYMBOL(l1_inst_sram_free); | |
553 | ||
554 | /* L1 Scratchpad memory allocate function */ | |
555 | void *l1sram_alloc(size_t size) | |
556 | { | |
226a6ec3 | 557 | unsigned long flags; |
1394f032 BW |
558 | void *addr; |
559 | ||
560 | /* add mutex operation */ | |
561 | spin_lock_irqsave(&l1sram_lock, flags); | |
562 | ||
262c3825 | 563 | addr = _sram_alloc(size, &free_l1_ssram_head, |
5d481f49 | 564 | &used_l1_ssram_head); |
1394f032 BW |
565 | |
566 | /* add mutex operation */ | |
567 | spin_unlock_irqrestore(&l1sram_lock, flags); | |
568 | ||
569 | return addr; | |
570 | } | |
571 | ||
572 | /* L1 Scratchpad memory allocate function */ | |
573 | void *l1sram_alloc_max(size_t *psize) | |
574 | { | |
226a6ec3 | 575 | unsigned long flags; |
1394f032 BW |
576 | void *addr; |
577 | ||
578 | /* add mutex operation */ | |
579 | spin_lock_irqsave(&l1sram_lock, flags); | |
580 | ||
262c3825 | 581 | addr = _sram_alloc_max(&free_l1_ssram_head, |
5d481f49 | 582 | &used_l1_ssram_head, psize); |
1394f032 BW |
583 | |
584 | /* add mutex operation */ | |
585 | spin_unlock_irqrestore(&l1sram_lock, flags); | |
586 | ||
587 | return addr; | |
588 | } | |
589 | ||
590 | /* L1 Scratchpad memory free function */ | |
591 | int l1sram_free(const void *addr) | |
592 | { | |
226a6ec3 | 593 | unsigned long flags; |
1394f032 BW |
594 | int ret; |
595 | ||
596 | /* add mutex operation */ | |
597 | spin_lock_irqsave(&l1sram_lock, flags); | |
598 | ||
262c3825 | 599 | ret = _sram_free(addr, &free_l1_ssram_head, |
5d481f49 | 600 | &used_l1_ssram_head); |
1394f032 BW |
601 | |
602 | /* add mutex operation */ | |
603 | spin_unlock_irqrestore(&l1sram_lock, flags); | |
604 | ||
605 | return ret; | |
606 | } | |
607 | ||
262c3825 SZ |
608 | void *l2_sram_alloc(size_t size) |
609 | { | |
07aa7be5 | 610 | #if L2_LENGTH != 0 |
226a6ec3 | 611 | unsigned long flags; |
262c3825 SZ |
612 | void *addr; |
613 | ||
614 | /* add mutex operation */ | |
615 | spin_lock_irqsave(&l2_sram_lock, flags); | |
616 | ||
617 | addr = _sram_alloc(size, &free_l2_sram_head, | |
618 | &used_l2_sram_head); | |
619 | ||
620 | /* add mutex operation */ | |
621 | spin_unlock_irqrestore(&l2_sram_lock, flags); | |
622 | ||
623 | pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n", | |
624 | (long unsigned int)addr, size); | |
625 | ||
626 | return addr; | |
627 | #else | |
628 | return NULL; | |
629 | #endif | |
630 | } | |
631 | EXPORT_SYMBOL(l2_sram_alloc); | |
632 | ||
633 | void *l2_sram_zalloc(size_t size) | |
634 | { | |
635 | void *addr = l2_sram_alloc(size); | |
636 | ||
637 | if (addr) | |
638 | memset(addr, 0x00, size); | |
639 | ||
640 | return addr; | |
641 | } | |
642 | EXPORT_SYMBOL(l2_sram_zalloc); | |
643 | ||
644 | int l2_sram_free(const void *addr) | |
645 | { | |
07aa7be5 | 646 | #if L2_LENGTH != 0 |
226a6ec3 | 647 | unsigned long flags; |
262c3825 SZ |
648 | int ret; |
649 | ||
650 | /* add mutex operation */ | |
651 | spin_lock_irqsave(&l2_sram_lock, flags); | |
652 | ||
653 | ret = _sram_free(addr, &free_l2_sram_head, | |
654 | &used_l2_sram_head); | |
655 | ||
656 | /* add mutex operation */ | |
657 | spin_unlock_irqrestore(&l2_sram_lock, flags); | |
658 | ||
659 | return ret; | |
660 | #else | |
661 | return -1; | |
662 | #endif | |
663 | } | |
664 | EXPORT_SYMBOL(l2_sram_free); | |
665 | ||
1394f032 BW |
666 | int sram_free_with_lsl(const void *addr) |
667 | { | |
668 | struct sram_list_struct *lsl, **tmp; | |
669 | struct mm_struct *mm = current->mm; | |
670 | ||
671 | for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next) | |
672 | if ((*tmp)->addr == addr) | |
673 | goto found; | |
674 | return -1; | |
675 | found: | |
676 | lsl = *tmp; | |
677 | sram_free(addr); | |
678 | *tmp = lsl->next; | |
679 | kfree(lsl); | |
680 | ||
681 | return 0; | |
682 | } | |
683 | EXPORT_SYMBOL(sram_free_with_lsl); | |
684 | ||
685 | void *sram_alloc_with_lsl(size_t size, unsigned long flags) | |
686 | { | |
687 | void *addr = NULL; | |
688 | struct sram_list_struct *lsl = NULL; | |
689 | struct mm_struct *mm = current->mm; | |
690 | ||
dd00cc48 | 691 | lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL); |
1394f032 BW |
692 | if (!lsl) |
693 | return NULL; | |
1394f032 BW |
694 | |
695 | if (flags & L1_INST_SRAM) | |
696 | addr = l1_inst_sram_alloc(size); | |
697 | ||
698 | if (addr == NULL && (flags & L1_DATA_A_SRAM)) | |
699 | addr = l1_data_A_sram_alloc(size); | |
700 | ||
701 | if (addr == NULL && (flags & L1_DATA_B_SRAM)) | |
702 | addr = l1_data_B_sram_alloc(size); | |
703 | ||
262c3825 SZ |
704 | if (addr == NULL && (flags & L2_SRAM)) |
705 | addr = l2_sram_alloc(size); | |
706 | ||
1394f032 BW |
707 | if (addr == NULL) { |
708 | kfree(lsl); | |
709 | return NULL; | |
710 | } | |
711 | lsl->addr = addr; | |
712 | lsl->length = size; | |
713 | lsl->next = mm->context.sram_list; | |
714 | mm->context.sram_list = lsl; | |
715 | return addr; | |
716 | } | |
717 | EXPORT_SYMBOL(sram_alloc_with_lsl); | |
bc61b4e6 MF |
718 | |
719 | #ifdef CONFIG_PROC_FS | |
720 | /* Once we get a real allocator, we'll throw all of this away. | |
721 | * Until then, we need some sort of visibility into the L1 alloc. | |
722 | */ | |
260d5d35 MF |
723 | /* Need to keep line of output the same. Currently, that is 44 bytes |
724 | * (including newline). | |
725 | */ | |
262c3825 | 726 | static int _sram_proc_read(char *buf, int *len, int count, const char *desc, |
5d481f49 SZ |
727 | struct sram_piece *pfree_head, |
728 | struct sram_piece *pused_head) | |
bc61b4e6 | 729 | { |
5d481f49 SZ |
730 | struct sram_piece *pslot; |
731 | ||
732 | if (!pfree_head || !pused_head) | |
733 | return -1; | |
bc61b4e6 | 734 | |
262c3825 | 735 | *len += sprintf(&buf[*len], "--- SRAM %-14s Size PID State \n", desc); |
5d481f49 SZ |
736 | |
737 | /* search the relevant memory slot */ | |
738 | pslot = pused_head->next; | |
739 | ||
740 | while (pslot != NULL) { | |
262c3825 | 741 | *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", |
5d481f49 SZ |
742 | pslot->paddr, pslot->paddr + pslot->size, |
743 | pslot->size, pslot->pid, "ALLOCATED"); | |
744 | ||
745 | pslot = pslot->next; | |
746 | } | |
747 | ||
748 | pslot = pfree_head->next; | |
749 | ||
750 | while (pslot != NULL) { | |
262c3825 | 751 | *len += sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n", |
5d481f49 SZ |
752 | pslot->paddr, pslot->paddr + pslot->size, |
753 | pslot->size, pslot->pid, "FREE"); | |
754 | ||
755 | pslot = pslot->next; | |
bc61b4e6 | 756 | } |
5d481f49 SZ |
757 | |
758 | return 0; | |
bc61b4e6 | 759 | } |
262c3825 | 760 | static int sram_proc_read(char *buf, char **start, off_t offset, int count, |
bc61b4e6 MF |
761 | int *eof, void *data) |
762 | { | |
763 | int len = 0; | |
764 | ||
262c3825 | 765 | if (_sram_proc_read(buf, &len, count, "Scratchpad", |
5d481f49 | 766 | &free_l1_ssram_head, &used_l1_ssram_head)) |
260d5d35 | 767 | goto not_done; |
bc61b4e6 | 768 | #if L1_DATA_A_LENGTH != 0 |
262c3825 | 769 | if (_sram_proc_read(buf, &len, count, "L1 Data A", |
5d481f49 SZ |
770 | &free_l1_data_A_sram_head, |
771 | &used_l1_data_A_sram_head)) | |
260d5d35 | 772 | goto not_done; |
bc61b4e6 MF |
773 | #endif |
774 | #if L1_DATA_B_LENGTH != 0 | |
262c3825 | 775 | if (_sram_proc_read(buf, &len, count, "L1 Data B", |
5d481f49 SZ |
776 | &free_l1_data_B_sram_head, |
777 | &used_l1_data_B_sram_head)) | |
260d5d35 | 778 | goto not_done; |
bc61b4e6 MF |
779 | #endif |
780 | #if L1_CODE_LENGTH != 0 | |
262c3825 | 781 | if (_sram_proc_read(buf, &len, count, "L1 Instruction", |
5d481f49 | 782 | &free_l1_inst_sram_head, &used_l1_inst_sram_head)) |
260d5d35 | 783 | goto not_done; |
bc61b4e6 | 784 | #endif |
07aa7be5 | 785 | #if L2_LENGTH != 0 |
262c3825 SZ |
786 | if (_sram_proc_read(buf, &len, count, "L2", |
787 | &free_l2_sram_head, &used_l2_sram_head)) | |
788 | goto not_done; | |
789 | #endif | |
bc61b4e6 | 790 | |
260d5d35 MF |
791 | *eof = 1; |
792 | not_done: | |
bc61b4e6 MF |
793 | return len; |
794 | } | |
795 | ||
262c3825 | 796 | static int __init sram_proc_init(void) |
bc61b4e6 MF |
797 | { |
798 | struct proc_dir_entry *ptr; | |
799 | ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL); | |
800 | if (!ptr) { | |
801 | printk(KERN_WARNING "unable to create /proc/sram\n"); | |
802 | return -1; | |
803 | } | |
804 | ptr->owner = THIS_MODULE; | |
262c3825 | 805 | ptr->read_proc = sram_proc_read; |
bc61b4e6 MF |
806 | return 0; |
807 | } | |
262c3825 | 808 | late_initcall(sram_proc_init); |
bc61b4e6 | 809 | #endif |