2 * File: arch/blackfin/mm/blackfin_sram.c
7 * Description: SRAM driver for Blackfin ADSP-BF5xx
10 * Copyright 2004-2007 Analog Devices Inc.
12 * Bugs: Enter bugs at http://blackfin.uclinux.org/
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.
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.
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
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"
44 static spinlock_t l1sram_lock
, l1_data_sram_lock
, l1_inst_sram_lock
;
45 static spinlock_t l2_sram_lock
;
47 /* the data structure for L1 scratchpad and DATA SRAM */
52 struct sram_piece
*next
;
55 static struct sram_piece free_l1_ssram_head
, used_l1_ssram_head
;
57 #if L1_DATA_A_LENGTH != 0
58 static struct sram_piece free_l1_data_A_sram_head
, used_l1_data_A_sram_head
;
61 #if L1_DATA_B_LENGTH != 0
62 static struct sram_piece free_l1_data_B_sram_head
, used_l1_data_B_sram_head
;
65 #if L1_CODE_LENGTH != 0
66 static struct sram_piece free_l1_inst_sram_head
, used_l1_inst_sram_head
;
70 static struct sram_piece free_l2_sram_head
, used_l2_sram_head
;
73 static struct kmem_cache
*sram_piece_cache
;
75 /* L1 Scratchpad SRAM initialization function */
76 static void __init
l1sram_init(void)
78 free_l1_ssram_head
.next
=
79 kmem_cache_alloc(sram_piece_cache
, GFP_KERNEL
);
80 if (!free_l1_ssram_head
.next
) {
81 printk(KERN_INFO
"Fail to initialize Scratchpad data SRAM.\n");
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
;
90 used_l1_ssram_head
.next
= NULL
;
92 /* mutex initialize */
93 spin_lock_init(&l1sram_lock
);
95 printk(KERN_INFO
"Blackfin Scratchpad data SRAM: %d KB\n",
96 L1_SCRATCH_LENGTH
>> 10);
99 static void __init
l1_data_sram_init(void)
101 #if L1_DATA_A_LENGTH != 0
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
) {
105 printk(KERN_INFO
"Fail to initialize L1 Data A SRAM.\n");
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
;
116 used_l1_data_A_sram_head
.next
= NULL
;
118 printk(KERN_INFO
"Blackfin L1 Data A SRAM: %d KB (%d KB free)\n",
119 L1_DATA_A_LENGTH
>> 10,
120 free_l1_data_A_sram_head
.next
->size
>> 10);
122 #if L1_DATA_B_LENGTH != 0
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
) {
126 printk(KERN_INFO
"Fail to initialize L1 Data B SRAM.\n");
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
;
137 used_l1_data_B_sram_head
.next
= NULL
;
139 printk(KERN_INFO
"Blackfin L1 Data B SRAM: %d KB (%d KB free)\n",
140 L1_DATA_B_LENGTH
>> 10,
141 free_l1_data_B_sram_head
.next
->size
>> 10);
144 /* mutex initialize */
145 spin_lock_init(&l1_data_sram_lock
);
148 static void __init
l1_inst_sram_init(void)
150 #if L1_CODE_LENGTH != 0
151 free_l1_inst_sram_head
.next
=
152 kmem_cache_alloc(sram_piece_cache
, GFP_KERNEL
);
153 if (!free_l1_inst_sram_head
.next
) {
154 printk(KERN_INFO
"Fail to initialize L1 Instruction SRAM.\n");
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
;
165 used_l1_inst_sram_head
.next
= NULL
;
167 printk(KERN_INFO
"Blackfin L1 Instruction SRAM: %d KB (%d KB free)\n",
168 L1_CODE_LENGTH
>> 10,
169 free_l1_inst_sram_head
.next
->size
>> 10);
172 /* mutex initialize */
173 spin_lock_init(&l1_inst_sram_lock
);
176 static void __init
l2_sram_init(void)
179 free_l2_sram_head
.next
=
180 kmem_cache_alloc(sram_piece_cache
, GFP_KERNEL
);
181 if (!free_l2_sram_head
.next
) {
182 printk(KERN_INFO
"Fail to initialize L2 SRAM.\n");
186 free_l2_sram_head
.next
->paddr
= (void *)L2_START
+
187 (_etext_l2
- _stext_l2
) + (_edata_l2
- _sdata_l2
);
188 free_l2_sram_head
.next
->size
= L2_LENGTH
-
189 (_etext_l2
- _stext_l2
) + (_edata_l2
- _sdata_l2
);
190 free_l2_sram_head
.next
->pid
= 0;
191 free_l2_sram_head
.next
->next
= NULL
;
193 used_l2_sram_head
.next
= NULL
;
195 printk(KERN_INFO
"Blackfin L2 SRAM: %d KB (%d KB free)\n",
197 free_l2_sram_head
.next
->size
>> 10);
200 /* mutex initialize */
201 spin_lock_init(&l2_sram_lock
);
203 void __init
bfin_sram_init(void)
205 sram_piece_cache
= kmem_cache_create("sram_piece_cache",
206 sizeof(struct sram_piece
),
207 0, SLAB_PANIC
, NULL
);
215 /* SRAM allocate function */
216 static void *_sram_alloc(size_t size
, struct sram_piece
*pfree_head
,
217 struct sram_piece
*pused_head
)
219 struct sram_piece
*pslot
, *plast
, *pavail
;
221 if (size
<= 0 || !pfree_head
|| !pused_head
)
225 size
= (size
+ 3) & ~3;
227 pslot
= pfree_head
->next
;
230 /* search an available piece slot */
231 while (pslot
!= NULL
&& size
> pslot
->size
) {
239 if (pslot
->size
== size
) {
240 plast
->next
= pslot
->next
;
243 pavail
= kmem_cache_alloc(sram_piece_cache
, GFP_KERNEL
);
248 pavail
->paddr
= pslot
->paddr
;
250 pslot
->paddr
+= size
;
254 pavail
->pid
= current
->pid
;
256 pslot
= pused_head
->next
;
259 /* insert new piece into used piece list !!! */
260 while (pslot
!= NULL
&& pavail
->paddr
< pslot
->paddr
) {
265 pavail
->next
= pslot
;
266 plast
->next
= pavail
;
268 return pavail
->paddr
;
271 /* Allocate the largest available block. */
272 static void *_sram_alloc_max(struct sram_piece
*pfree_head
,
273 struct sram_piece
*pused_head
,
274 unsigned long *psize
)
276 struct sram_piece
*pslot
, *pmax
;
278 if (!pfree_head
|| !pused_head
)
281 pmax
= pslot
= pfree_head
->next
;
283 /* search an available piece slot */
284 while (pslot
!= NULL
) {
285 if (pslot
->size
> pmax
->size
)
295 return _sram_alloc(*psize
, pfree_head
, pused_head
);
298 /* SRAM free function */
299 static int _sram_free(const void *addr
,
300 struct sram_piece
*pfree_head
,
301 struct sram_piece
*pused_head
)
303 struct sram_piece
*pslot
, *plast
, *pavail
;
305 if (!pfree_head
|| !pused_head
)
308 /* search the relevant memory slot */
309 pslot
= pused_head
->next
;
312 /* search an available piece slot */
313 while (pslot
!= NULL
&& pslot
->paddr
!= addr
) {
321 plast
->next
= pslot
->next
;
325 /* insert free pieces back to the free list */
326 pslot
= pfree_head
->next
;
329 while (pslot
!= NULL
&& addr
> pslot
->paddr
) {
334 if (plast
!= pfree_head
&& plast
->paddr
+ plast
->size
== pavail
->paddr
) {
335 plast
->size
+= pavail
->size
;
336 kmem_cache_free(sram_piece_cache
, pavail
);
338 pavail
->next
= plast
->next
;
339 plast
->next
= pavail
;
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
);
352 int sram_free(const void *addr
)
355 #if L1_CODE_LENGTH != 0
356 else if (addr
>= (void *)L1_CODE_START
357 && addr
< (void *)(L1_CODE_START
+ L1_CODE_LENGTH
))
358 return l1_inst_sram_free(addr
);
360 #if L1_DATA_A_LENGTH != 0
361 else if (addr
>= (void *)L1_DATA_A_START
362 && addr
< (void *)(L1_DATA_A_START
+ L1_DATA_A_LENGTH
))
363 return l1_data_A_sram_free(addr
);
365 #if L1_DATA_B_LENGTH != 0
366 else if (addr
>= (void *)L1_DATA_B_START
367 && addr
< (void *)(L1_DATA_B_START
+ L1_DATA_B_LENGTH
))
368 return l1_data_B_sram_free(addr
);
371 else if (addr
>= (void *)L2_START
372 && addr
< (void *)(L2_START
+ L2_LENGTH
))
373 return l2_sram_free(addr
);
378 EXPORT_SYMBOL(sram_free
);
380 void *l1_data_A_sram_alloc(size_t size
)
385 /* add mutex operation */
386 spin_lock_irqsave(&l1_data_sram_lock
, flags
);
388 #if L1_DATA_A_LENGTH != 0
389 addr
= _sram_alloc(size
, &free_l1_data_A_sram_head
,
390 &used_l1_data_A_sram_head
);
393 /* add mutex operation */
394 spin_unlock_irqrestore(&l1_data_sram_lock
, flags
);
396 pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n",
397 (long unsigned int)addr
, size
);
401 EXPORT_SYMBOL(l1_data_A_sram_alloc
);
403 int l1_data_A_sram_free(const void *addr
)
408 /* add mutex operation */
409 spin_lock_irqsave(&l1_data_sram_lock
, flags
);
411 #if L1_DATA_A_LENGTH != 0
412 ret
= _sram_free(addr
, &free_l1_data_A_sram_head
,
413 &used_l1_data_A_sram_head
);
418 /* add mutex operation */
419 spin_unlock_irqrestore(&l1_data_sram_lock
, flags
);
423 EXPORT_SYMBOL(l1_data_A_sram_free
);
425 void *l1_data_B_sram_alloc(size_t size
)
427 #if L1_DATA_B_LENGTH != 0
431 /* add mutex operation */
432 spin_lock_irqsave(&l1_data_sram_lock
, flags
);
434 addr
= _sram_alloc(size
, &free_l1_data_B_sram_head
,
435 &used_l1_data_B_sram_head
);
437 /* add mutex operation */
438 spin_unlock_irqrestore(&l1_data_sram_lock
, flags
);
440 pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n",
441 (long unsigned int)addr
, size
);
448 EXPORT_SYMBOL(l1_data_B_sram_alloc
);
450 int l1_data_B_sram_free(const void *addr
)
452 #if L1_DATA_B_LENGTH != 0
456 /* add mutex operation */
457 spin_lock_irqsave(&l1_data_sram_lock
, flags
);
459 ret
= _sram_free(addr
, &free_l1_data_B_sram_head
,
460 &used_l1_data_B_sram_head
);
462 /* add mutex operation */
463 spin_unlock_irqrestore(&l1_data_sram_lock
, flags
);
470 EXPORT_SYMBOL(l1_data_B_sram_free
);
472 void *l1_data_sram_alloc(size_t size
)
474 void *addr
= l1_data_A_sram_alloc(size
);
477 addr
= l1_data_B_sram_alloc(size
);
481 EXPORT_SYMBOL(l1_data_sram_alloc
);
483 void *l1_data_sram_zalloc(size_t size
)
485 void *addr
= l1_data_sram_alloc(size
);
488 memset(addr
, 0x00, size
);
492 EXPORT_SYMBOL(l1_data_sram_zalloc
);
494 int l1_data_sram_free(const void *addr
)
497 ret
= l1_data_A_sram_free(addr
);
499 ret
= l1_data_B_sram_free(addr
);
502 EXPORT_SYMBOL(l1_data_sram_free
);
504 void *l1_inst_sram_alloc(size_t size
)
506 #if L1_CODE_LENGTH != 0
510 /* add mutex operation */
511 spin_lock_irqsave(&l1_inst_sram_lock
, flags
);
513 addr
= _sram_alloc(size
, &free_l1_inst_sram_head
,
514 &used_l1_inst_sram_head
);
516 /* add mutex operation */
517 spin_unlock_irqrestore(&l1_inst_sram_lock
, flags
);
519 pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n",
520 (long unsigned int)addr
, size
);
527 EXPORT_SYMBOL(l1_inst_sram_alloc
);
529 int l1_inst_sram_free(const void *addr
)
531 #if L1_CODE_LENGTH != 0
535 /* add mutex operation */
536 spin_lock_irqsave(&l1_inst_sram_lock
, flags
);
538 ret
= _sram_free(addr
, &free_l1_inst_sram_head
,
539 &used_l1_inst_sram_head
);
541 /* add mutex operation */
542 spin_unlock_irqrestore(&l1_inst_sram_lock
, flags
);
549 EXPORT_SYMBOL(l1_inst_sram_free
);
551 /* L1 Scratchpad memory allocate function */
552 void *l1sram_alloc(size_t size
)
557 /* add mutex operation */
558 spin_lock_irqsave(&l1sram_lock
, flags
);
560 addr
= _sram_alloc(size
, &free_l1_ssram_head
,
561 &used_l1_ssram_head
);
563 /* add mutex operation */
564 spin_unlock_irqrestore(&l1sram_lock
, flags
);
569 /* L1 Scratchpad memory allocate function */
570 void *l1sram_alloc_max(size_t *psize
)
575 /* add mutex operation */
576 spin_lock_irqsave(&l1sram_lock
, flags
);
578 addr
= _sram_alloc_max(&free_l1_ssram_head
,
579 &used_l1_ssram_head
, psize
);
581 /* add mutex operation */
582 spin_unlock_irqrestore(&l1sram_lock
, flags
);
587 /* L1 Scratchpad memory free function */
588 int l1sram_free(const void *addr
)
593 /* add mutex operation */
594 spin_lock_irqsave(&l1sram_lock
, flags
);
596 ret
= _sram_free(addr
, &free_l1_ssram_head
,
597 &used_l1_ssram_head
);
599 /* add mutex operation */
600 spin_unlock_irqrestore(&l1sram_lock
, flags
);
605 void *l2_sram_alloc(size_t size
)
611 /* add mutex operation */
612 spin_lock_irqsave(&l2_sram_lock
, flags
);
614 addr
= _sram_alloc(size
, &free_l2_sram_head
,
617 /* add mutex operation */
618 spin_unlock_irqrestore(&l2_sram_lock
, flags
);
620 pr_debug("Allocated address in l2_sram_alloc is 0x%lx+0x%lx\n",
621 (long unsigned int)addr
, size
);
628 EXPORT_SYMBOL(l2_sram_alloc
);
630 void *l2_sram_zalloc(size_t size
)
632 void *addr
= l2_sram_alloc(size
);
635 memset(addr
, 0x00, size
);
639 EXPORT_SYMBOL(l2_sram_zalloc
);
641 int l2_sram_free(const void *addr
)
647 /* add mutex operation */
648 spin_lock_irqsave(&l2_sram_lock
, flags
);
650 ret
= _sram_free(addr
, &free_l2_sram_head
,
653 /* add mutex operation */
654 spin_unlock_irqrestore(&l2_sram_lock
, flags
);
661 EXPORT_SYMBOL(l2_sram_free
);
663 int sram_free_with_lsl(const void *addr
)
665 struct sram_list_struct
*lsl
, **tmp
;
666 struct mm_struct
*mm
= current
->mm
;
668 for (tmp
= &mm
->context
.sram_list
; *tmp
; tmp
= &(*tmp
)->next
)
669 if ((*tmp
)->addr
== addr
)
680 EXPORT_SYMBOL(sram_free_with_lsl
);
682 void *sram_alloc_with_lsl(size_t size
, unsigned long flags
)
685 struct sram_list_struct
*lsl
= NULL
;
686 struct mm_struct
*mm
= current
->mm
;
688 lsl
= kzalloc(sizeof(struct sram_list_struct
), GFP_KERNEL
);
692 if (flags
& L1_INST_SRAM
)
693 addr
= l1_inst_sram_alloc(size
);
695 if (addr
== NULL
&& (flags
& L1_DATA_A_SRAM
))
696 addr
= l1_data_A_sram_alloc(size
);
698 if (addr
== NULL
&& (flags
& L1_DATA_B_SRAM
))
699 addr
= l1_data_B_sram_alloc(size
);
701 if (addr
== NULL
&& (flags
& L2_SRAM
))
702 addr
= l2_sram_alloc(size
);
710 lsl
->next
= mm
->context
.sram_list
;
711 mm
->context
.sram_list
= lsl
;
714 EXPORT_SYMBOL(sram_alloc_with_lsl
);
716 #ifdef CONFIG_PROC_FS
717 /* Once we get a real allocator, we'll throw all of this away.
718 * Until then, we need some sort of visibility into the L1 alloc.
720 /* Need to keep line of output the same. Currently, that is 44 bytes
721 * (including newline).
723 static int _sram_proc_read(char *buf
, int *len
, int count
, const char *desc
,
724 struct sram_piece
*pfree_head
,
725 struct sram_piece
*pused_head
)
727 struct sram_piece
*pslot
;
729 if (!pfree_head
|| !pused_head
)
732 *len
+= sprintf(&buf
[*len
], "--- SRAM %-14s Size PID State \n", desc
);
734 /* search the relevant memory slot */
735 pslot
= pused_head
->next
;
737 while (pslot
!= NULL
) {
738 *len
+= sprintf(&buf
[*len
], "%p-%p %10i %5i %-10s\n",
739 pslot
->paddr
, pslot
->paddr
+ pslot
->size
,
740 pslot
->size
, pslot
->pid
, "ALLOCATED");
745 pslot
= pfree_head
->next
;
747 while (pslot
!= NULL
) {
748 *len
+= sprintf(&buf
[*len
], "%p-%p %10i %5i %-10s\n",
749 pslot
->paddr
, pslot
->paddr
+ pslot
->size
,
750 pslot
->size
, pslot
->pid
, "FREE");
757 static int sram_proc_read(char *buf
, char **start
, off_t offset
, int count
,
758 int *eof
, void *data
)
762 if (_sram_proc_read(buf
, &len
, count
, "Scratchpad",
763 &free_l1_ssram_head
, &used_l1_ssram_head
))
765 #if L1_DATA_A_LENGTH != 0
766 if (_sram_proc_read(buf
, &len
, count
, "L1 Data A",
767 &free_l1_data_A_sram_head
,
768 &used_l1_data_A_sram_head
))
771 #if L1_DATA_B_LENGTH != 0
772 if (_sram_proc_read(buf
, &len
, count
, "L1 Data B",
773 &free_l1_data_B_sram_head
,
774 &used_l1_data_B_sram_head
))
777 #if L1_CODE_LENGTH != 0
778 if (_sram_proc_read(buf
, &len
, count
, "L1 Instruction",
779 &free_l1_inst_sram_head
, &used_l1_inst_sram_head
))
783 if (_sram_proc_read(buf
, &len
, count
, "L2",
784 &free_l2_sram_head
, &used_l2_sram_head
))
793 static int __init
sram_proc_init(void)
795 struct proc_dir_entry
*ptr
;
796 ptr
= create_proc_entry("sram", S_IFREG
| S_IRUGO
, NULL
);
798 printk(KERN_WARNING
"unable to create /proc/sram\n");
801 ptr
->owner
= THIS_MODULE
;
802 ptr
->read_proc
= sram_proc_read
;
805 late_initcall(sram_proc_init
);