1717 * published by the Free Software Foundation.
1818 */
1919
20+ #include <linux/genalloc.h>
2021#include <linux/init.h>
2122#include <linux/of_device.h>
2223#include <linux/spinlock.h>
2728
2829#include <asm/udbg.h>
2930#include <asm/io.h>
30- #include <asm/rheap.h>
3131#include <asm/cpm.h>
3232
3333#include <mm/mmu_decl.h>
@@ -65,14 +65,22 @@ void __init udbg_init_cpm(void)
6565}
6666#endif
6767
68+ static struct gen_pool * muram_pool ;
6869static spinlock_t cpm_muram_lock ;
69- static rh_block_t cpm_boot_muram_rh_block [16 ];
70- static rh_info_t cpm_muram_info ;
7170static u8 __iomem * muram_vbase ;
7271static phys_addr_t muram_pbase ;
7372
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 */
7582#define OF_MAX_ADDR_CELLS 4
83+ #define GENPOOL_OFFSET (4096 * 8)
7684
7785int cpm_muram_init (void )
7886{
@@ -87,50 +95,51 @@ int cpm_muram_init(void)
8795 return 0 ;
8896
8997 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-
9698 np = of_find_compatible_node (NULL , NULL , "fsl,cpm-muram-data" );
9799 if (!np ) {
98100 /* try legacy bindings */
99101 np = of_find_node_by_name (NULL , "data-only" );
100102 if (!np ) {
101- printk ( KERN_ERR "Cannot find CPM muram data node" );
103+ pr_err ( "Cannot find CPM muram data node" );
102104 ret = - ENODEV ;
103- goto out ;
105+ goto out_muram ;
104106 }
105107 }
106108
109+ muram_pool = gen_pool_create (0 , -1 );
107110 muram_pbase = of_translate_address (np , zero );
108111 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" );
110113 ret = - ENODEV ;
111- goto out ;
114+ goto out_pool ;
112115 }
113116
114117 while (of_address_to_resource (np , i ++ , & r ) == 0 ) {
115118 if (r .end > max )
116119 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+ }
120126 }
121127
122128 muram_vbase = ioremap (muram_pbase , max - muram_pbase + 1 );
123129 if (!muram_vbase ) {
124- printk ( KERN_ERR "Cannot map CPM muram" );
130+ pr_err ( "Cannot map QE muram" );
125131 ret = - ENOMEM ;
132+ goto out_pool ;
126133 }
127-
128- out :
134+ goto out_muram ;
135+ out_pool :
136+ gen_pool_destroy (muram_pool );
137+ out_muram :
129138 of_node_put (np );
130139 return ret ;
131140}
132141
133- /**
142+ /*
134143 * cpm_muram_alloc - allocate the requested size worth of multi-user ram
135144 * @size: number of bytes to allocate
136145 * @align: requested alignment, in bytes
@@ -143,14 +152,13 @@ unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
143152{
144153 unsigned long start ;
145154 unsigned long flags ;
155+ struct genpool_data_align muram_pool_data ;
146156
147157 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 );
152161 spin_unlock_irqrestore (& cpm_muram_lock , flags );
153-
154162 return start ;
155163}
156164EXPORT_SYMBOL (cpm_muram_alloc );
@@ -161,40 +169,82 @@ EXPORT_SYMBOL(cpm_muram_alloc);
161169 */
162170int cpm_muram_free (unsigned long offset )
163171{
164- int ret ;
165172 unsigned long flags ;
173+ int size ;
174+ struct muram_block * tmp ;
166175
176+ size = 0 ;
167177 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 );
169187 spin_unlock_irqrestore (& cpm_muram_lock , flags );
170-
171- return ret ;
188+ return size ;
172189}
173190EXPORT_SYMBOL (cpm_muram_free );
174191
175- /**
192+ /*
176193 * 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
181197 * Use cpm_dpram_addr() to get the virtual address of the area.
182198 * Use cpm_muram_free() to free the allocation.
183199 */
184200unsigned long cpm_muram_alloc_fixed (unsigned long offset , unsigned long size )
185201{
186202 unsigned long start ;
187203 unsigned long flags ;
204+ struct genpool_data_fixed muram_pool_data_fixed ;
188205
189206 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 );
192210 spin_unlock_irqrestore (& cpm_muram_lock , flags );
193-
194211 return start ;
195212}
196213EXPORT_SYMBOL (cpm_muram_alloc_fixed );
197214
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+
198248/**
199249 * cpm_muram_addr - turn a muram offset into a virtual address
200250 * @offset: muram offset to convert
0 commit comments