17
17
* published by the Free Software Foundation.
18
18
*/
19
19
20
+ #include <linux/genalloc.h>
20
21
#include <linux/init.h>
21
22
#include <linux/of_device.h>
22
23
#include <linux/spinlock.h>
27
28
28
29
#include <asm/udbg.h>
29
30
#include <asm/io.h>
30
- #include <asm/rheap.h>
31
31
#include <asm/cpm.h>
32
32
33
33
#include <mm/mmu_decl.h>
@@ -65,14 +65,22 @@ void __init udbg_init_cpm(void)
65
65
}
66
66
#endif
67
67
68
+ static struct gen_pool * muram_pool ;
68
69
static spinlock_t cpm_muram_lock ;
69
- static rh_block_t cpm_boot_muram_rh_block [16 ];
70
- static rh_info_t cpm_muram_info ;
71
70
static u8 __iomem * muram_vbase ;
72
71
static phys_addr_t muram_pbase ;
73
72
74
- /* Max address size we deal with */
73
+ struct muram_block {
74
+ struct list_head head ;
75
+ unsigned long start ;
76
+ int size ;
77
+ };
78
+
79
+ static LIST_HEAD (muram_block_list );
80
+
81
+ /* max address size we deal with */
75
82
#define OF_MAX_ADDR_CELLS 4
83
+ #define GENPOOL_OFFSET (4096 * 8)
76
84
77
85
int cpm_muram_init (void )
78
86
{
@@ -87,50 +95,51 @@ int cpm_muram_init(void)
87
95
return 0 ;
88
96
89
97
spin_lock_init (& cpm_muram_lock );
90
- /* initialize the info header */
91
- rh_init (& cpm_muram_info , 1 ,
92
- sizeof (cpm_boot_muram_rh_block ) /
93
- sizeof (cpm_boot_muram_rh_block [0 ]),
94
- cpm_boot_muram_rh_block );
95
-
96
98
np = of_find_compatible_node (NULL , NULL , "fsl,cpm-muram-data" );
97
99
if (!np ) {
98
100
/* try legacy bindings */
99
101
np = of_find_node_by_name (NULL , "data-only" );
100
102
if (!np ) {
101
- printk ( KERN_ERR "Cannot find CPM muram data node" );
103
+ pr_err ( "Cannot find CPM muram data node" );
102
104
ret = - ENODEV ;
103
- goto out ;
105
+ goto out_muram ;
104
106
}
105
107
}
106
108
109
+ muram_pool = gen_pool_create (0 , -1 );
107
110
muram_pbase = of_translate_address (np , zero );
108
111
if (muram_pbase == (phys_addr_t )OF_BAD_ADDR ) {
109
- printk ( KERN_ERR "Cannot translate zero through CPM muram node" );
112
+ pr_err ( "Cannot translate zero through CPM muram node" );
110
113
ret = - ENODEV ;
111
- goto out ;
114
+ goto out_pool ;
112
115
}
113
116
114
117
while (of_address_to_resource (np , i ++ , & r ) == 0 ) {
115
118
if (r .end > max )
116
119
max = r .end ;
117
-
118
- rh_attach_region (& cpm_muram_info , r .start - muram_pbase ,
119
- resource_size (& r ));
120
+ ret = gen_pool_add (muram_pool , r .start - muram_pbase +
121
+ GENPOOL_OFFSET , resource_size (& r ), -1 );
122
+ if (ret ) {
123
+ pr_err ("QE: couldn't add muram to pool!\n" );
124
+ goto out_pool ;
125
+ }
120
126
}
121
127
122
128
muram_vbase = ioremap (muram_pbase , max - muram_pbase + 1 );
123
129
if (!muram_vbase ) {
124
- printk ( KERN_ERR "Cannot map CPM muram" );
130
+ pr_err ( "Cannot map QE muram" );
125
131
ret = - ENOMEM ;
132
+ goto out_pool ;
126
133
}
127
-
128
- out :
134
+ goto out_muram ;
135
+ out_pool :
136
+ gen_pool_destroy (muram_pool );
137
+ out_muram :
129
138
of_node_put (np );
130
139
return ret ;
131
140
}
132
141
133
- /**
142
+ /*
134
143
* cpm_muram_alloc - allocate the requested size worth of multi-user ram
135
144
* @size: number of bytes to allocate
136
145
* @align: requested alignment, in bytes
@@ -143,14 +152,13 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
143
152
{
144
153
unsigned long start ;
145
154
unsigned long flags ;
155
+ struct genpool_data_align muram_pool_data ;
146
156
147
157
spin_lock_irqsave (& cpm_muram_lock , flags );
148
- cpm_muram_info .alignment = align ;
149
- start = rh_alloc (& cpm_muram_info , size , "commproc" );
150
- if (!IS_ERR_VALUE (start ))
151
- memset_io (cpm_muram_addr (start ), 0 , size );
158
+ muram_pool_data .align = align ;
159
+ start = cpm_muram_alloc_common (size , gen_pool_first_fit_align ,
160
+ & muram_pool_data );
152
161
spin_unlock_irqrestore (& cpm_muram_lock , flags );
153
-
154
162
return start ;
155
163
}
156
164
EXPORT_SYMBOL (cpm_muram_alloc );
@@ -161,40 +169,82 @@ EXPORT_SYMBOL(cpm_muram_alloc);
161
169
*/
162
170
int cpm_muram_free (unsigned long offset )
163
171
{
164
- int ret ;
165
172
unsigned long flags ;
173
+ int size ;
174
+ struct muram_block * tmp ;
166
175
176
+ size = 0 ;
167
177
spin_lock_irqsave (& cpm_muram_lock , flags );
168
- ret = rh_free (& cpm_muram_info , offset );
178
+ list_for_each_entry (tmp , & muram_block_list , head ) {
179
+ if (tmp -> start == offset ) {
180
+ size = tmp -> size ;
181
+ list_del (& tmp -> head );
182
+ kfree (tmp );
183
+ break ;
184
+ }
185
+ }
186
+ gen_pool_free (muram_pool , offset + GENPOOL_OFFSET , size );
169
187
spin_unlock_irqrestore (& cpm_muram_lock , flags );
170
-
171
- return ret ;
188
+ return size ;
172
189
}
173
190
EXPORT_SYMBOL (cpm_muram_free );
174
191
175
- /**
192
+ /*
176
193
* cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
177
- * @offset: the offset into the muram area to reserve
178
- * @size: the number of bytes to reserve
179
- *
180
- * This function returns "start" on success, -ENOMEM on failure.
194
+ * @offset: offset of allocation start address
195
+ * @size: number of bytes to allocate
196
+ * This function returns an offset into the muram area
181
197
* Use cpm_dpram_addr() to get the virtual address of the area.
182
198
* Use cpm_muram_free() to free the allocation.
183
199
*/
184
200
unsigned long cpm_muram_alloc_fixed (unsigned long offset , unsigned long size )
185
201
{
186
202
unsigned long start ;
187
203
unsigned long flags ;
204
+ struct genpool_data_fixed muram_pool_data_fixed ;
188
205
189
206
spin_lock_irqsave (& cpm_muram_lock , flags );
190
- cpm_muram_info .alignment = 1 ;
191
- start = rh_alloc_fixed (& cpm_muram_info , offset , size , "commproc" );
207
+ muram_pool_data_fixed .offset = offset + GENPOOL_OFFSET ;
208
+ start = cpm_muram_alloc_common (size , gen_pool_fixed_alloc ,
209
+ & muram_pool_data_fixed );
192
210
spin_unlock_irqrestore (& cpm_muram_lock , flags );
193
-
194
211
return start ;
195
212
}
196
213
EXPORT_SYMBOL (cpm_muram_alloc_fixed );
197
214
215
+ /*
216
+ * cpm_muram_alloc_common - cpm_muram_alloc common code
217
+ * @size: number of bytes to allocate
218
+ * @algo: algorithm for alloc.
219
+ * @data: data for genalloc's algorithm.
220
+ *
221
+ * This function returns an offset into the muram area.
222
+ */
223
+ unsigned long cpm_muram_alloc_common (unsigned long size , genpool_algo_t algo ,
224
+ void * data )
225
+ {
226
+ struct muram_block * entry ;
227
+ unsigned long start ;
228
+
229
+ start = gen_pool_alloc_algo (muram_pool , size , algo , data );
230
+ if (!start )
231
+ goto out2 ;
232
+ start = start - GENPOOL_OFFSET ;
233
+ memset_io (cpm_muram_addr (start ), 0 , size );
234
+ entry = kmalloc (sizeof (* entry ), GFP_KERNEL );
235
+ if (!entry )
236
+ goto out1 ;
237
+ entry -> start = start ;
238
+ entry -> size = size ;
239
+ list_add (& entry -> head , & muram_block_list );
240
+
241
+ return start ;
242
+ out1 :
243
+ gen_pool_free (muram_pool , start , size );
244
+ out2 :
245
+ return (unsigned long )- ENOMEM ;
246
+ }
247
+
198
248
/**
199
249
* cpm_muram_addr - turn a muram offset into a virtual address
200
250
* @offset: muram offset to convert
0 commit comments