diff options
Diffstat (limited to 'arch/powerpc/sysdev/bestcomm/sram.c')
-rw-r--r-- | arch/powerpc/sysdev/bestcomm/sram.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/bestcomm/sram.c b/arch/powerpc/sysdev/bestcomm/sram.c new file mode 100644 index 000000000000..99784383a843 --- /dev/null +++ b/arch/powerpc/sysdev/bestcomm/sram.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * Simple memory allocator for on-board SRAM | ||
3 | * | ||
4 | * | ||
5 | * Maintainer : Sylvain Munaut <tnt@246tNt.com> | ||
6 | * | ||
7 | * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.com> | ||
8 | * | ||
9 | * This file is licensed under the terms of the GNU General Public License | ||
10 | * version 2. This program is licensed "as is" without any warranty of any | ||
11 | * kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/of.h> | ||
21 | |||
22 | #include <asm/io.h> | ||
23 | #include <asm/mmu.h> | ||
24 | |||
25 | #include "sram.h" | ||
26 | |||
27 | |||
28 | /* Struct keeping our 'state' */ | ||
29 | struct bcom_sram *bcom_sram = NULL; | ||
30 | EXPORT_SYMBOL_GPL(bcom_sram); /* needed for inline functions */ | ||
31 | |||
32 | |||
33 | /* ======================================================================== */ | ||
34 | /* Public API */ | ||
35 | /* ======================================================================== */ | ||
36 | /* DO NOT USE in interrupts, if needed in irq handler, we should use the | ||
37 | _irqsave version of the spin_locks */ | ||
38 | |||
39 | int bcom_sram_init(struct device_node *sram_node, char *owner) | ||
40 | { | ||
41 | int rv; | ||
42 | const u32 *regaddr_p; | ||
43 | u64 regaddr64, size64; | ||
44 | unsigned int psize; | ||
45 | |||
46 | /* Create our state struct */ | ||
47 | if (bcom_sram) { | ||
48 | printk(KERN_ERR "%s: bcom_sram_init: " | ||
49 | "Already initialized !\n", owner); | ||
50 | return -EBUSY; | ||
51 | } | ||
52 | |||
53 | bcom_sram = kmalloc(sizeof(struct bcom_sram), GFP_KERNEL); | ||
54 | if (!bcom_sram) { | ||
55 | printk(KERN_ERR "%s: bcom_sram_init: " | ||
56 | "Couldn't allocate internal state !\n", owner); | ||
57 | return -ENOMEM; | ||
58 | } | ||
59 | |||
60 | /* Get address and size of the sram */ | ||
61 | regaddr_p = of_get_address(sram_node, 0, &size64, NULL); | ||
62 | if (!regaddr_p) { | ||
63 | printk(KERN_ERR "%s: bcom_sram_init: " | ||
64 | "Invalid device node !\n", owner); | ||
65 | rv = -EINVAL; | ||
66 | goto error_free; | ||
67 | } | ||
68 | |||
69 | regaddr64 = of_translate_address(sram_node, regaddr_p); | ||
70 | |||
71 | bcom_sram->base_phys = (phys_addr_t) regaddr64; | ||
72 | bcom_sram->size = (unsigned int) size64; | ||
73 | |||
74 | /* Request region */ | ||
75 | if (!request_mem_region(bcom_sram->base_phys, bcom_sram->size, owner)) { | ||
76 | printk(KERN_ERR "%s: bcom_sram_init: " | ||
77 | "Couldn't request region !\n", owner); | ||
78 | rv = -EBUSY; | ||
79 | goto error_free; | ||
80 | } | ||
81 | |||
82 | /* Map SRAM */ | ||
83 | /* sram is not really __iomem */ | ||
84 | bcom_sram->base_virt = (void*) ioremap(bcom_sram->base_phys, bcom_sram->size); | ||
85 | |||
86 | if (!bcom_sram->base_virt) { | ||
87 | printk(KERN_ERR "%s: bcom_sram_init: " | ||
88 | "Map error SRAM zone 0x%08lx (0x%0x)!\n", | ||
89 | owner, bcom_sram->base_phys, bcom_sram->size ); | ||
90 | rv = -ENOMEM; | ||
91 | goto error_release; | ||
92 | } | ||
93 | |||
94 | /* Create an rheap (defaults to 32 bits word alignment) */ | ||
95 | bcom_sram->rh = rh_create(4); | ||
96 | |||
97 | /* Attach the free zones */ | ||
98 | #if 0 | ||
99 | /* Currently disabled ... for future use only */ | ||
100 | reg_addr_p = of_get_property(sram_node, "available", &psize); | ||
101 | #else | ||
102 | regaddr_p = NULL; | ||
103 | psize = 0; | ||
104 | #endif | ||
105 | |||
106 | if (!regaddr_p || !psize) { | ||
107 | /* Attach the whole zone */ | ||
108 | rh_attach_region(bcom_sram->rh, 0, bcom_sram->size); | ||
109 | } else { | ||
110 | /* Attach each zone independently */ | ||
111 | while (psize >= 2 * sizeof(u32)) { | ||
112 | phys_addr_t zbase = of_translate_address(sram_node, regaddr_p); | ||
113 | rh_attach_region(bcom_sram->rh, zbase - bcom_sram->base_phys, regaddr_p[1]); | ||
114 | regaddr_p += 2; | ||
115 | psize -= 2 * sizeof(u32); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /* Init our spinlock */ | ||
120 | spin_lock_init(&bcom_sram->lock); | ||
121 | |||
122 | return 0; | ||
123 | |||
124 | error_release: | ||
125 | release_mem_region(bcom_sram->base_phys, bcom_sram->size); | ||
126 | error_free: | ||
127 | kfree(bcom_sram); | ||
128 | bcom_sram = NULL; | ||
129 | |||
130 | return rv; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(bcom_sram_init); | ||
133 | |||
134 | void bcom_sram_cleanup(void) | ||
135 | { | ||
136 | /* Free resources */ | ||
137 | if (bcom_sram) { | ||
138 | rh_destroy(bcom_sram->rh); | ||
139 | iounmap((void __iomem *)bcom_sram->base_virt); | ||
140 | release_mem_region(bcom_sram->base_phys, bcom_sram->size); | ||
141 | kfree(bcom_sram); | ||
142 | bcom_sram = NULL; | ||
143 | } | ||
144 | } | ||
145 | EXPORT_SYMBOL_GPL(bcom_sram_cleanup); | ||
146 | |||
147 | void* bcom_sram_alloc(int size, int align, phys_addr_t *phys) | ||
148 | { | ||
149 | unsigned long offset; | ||
150 | |||
151 | spin_lock(&bcom_sram->lock); | ||
152 | offset = rh_alloc_align(bcom_sram->rh, size, align, NULL); | ||
153 | spin_unlock(&bcom_sram->lock); | ||
154 | |||
155 | if (IS_ERR_VALUE(offset)) | ||
156 | return NULL; | ||
157 | |||
158 | *phys = bcom_sram->base_phys + offset; | ||
159 | return bcom_sram->base_virt + offset; | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(bcom_sram_alloc); | ||
162 | |||
163 | void bcom_sram_free(void *ptr) | ||
164 | { | ||
165 | unsigned long offset; | ||
166 | |||
167 | if (!ptr) | ||
168 | return; | ||
169 | |||
170 | offset = ptr - bcom_sram->base_virt; | ||
171 | |||
172 | spin_lock(&bcom_sram->lock); | ||
173 | rh_free(bcom_sram->rh, offset); | ||
174 | spin_unlock(&bcom_sram->lock); | ||
175 | } | ||
176 | EXPORT_SYMBOL_GPL(bcom_sram_free); | ||
177 | |||