aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/cpm_common.c
diff options
context:
space:
mode:
authorZhao Qiang <qiang.zhao@freescale.com>2015-11-29 21:48:55 -0500
committerScott Wood <scottwood@freescale.com>2015-12-22 18:10:18 -0500
commit1291e49e893703e04e129fe2e17e87af40757bf1 (patch)
treea256a6a6e4b3a1ded6d08afe17ce19ee20aac5dd /arch/powerpc/sysdev/cpm_common.c
parent0e6e01ff694ee222acc5a9184211678473c948e3 (diff)
QE/CPM: move muram management functions to qe_common
QE and CPM have the same muram, they use the same management functions. Now QE support both ARM and PowerPC, it is necessary to move QE to "driver/soc", so move the muram management functions from cpm_common to qe_common for preparing to move QE code to "driver/soc" Signed-off-by: Zhao Qiang <qiang.zhao@freescale.com> Signed-off-by: Scott Wood <scottwood@freescale.com>
Diffstat (limited to 'arch/powerpc/sysdev/cpm_common.c')
-rw-r--r--arch/powerpc/sysdev/cpm_common.c208
1 files changed, 1 insertions, 207 deletions
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index fcc83cd9cc2f..6993aa8e7242 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -17,7 +17,6 @@
17 * published by the Free Software Foundation. 17 * published by the Free Software Foundation.
18 */ 18 */
19 19
20#include <linux/genalloc.h>
21#include <linux/init.h> 20#include <linux/init.h>
22#include <linux/of_device.h> 21#include <linux/of_device.h>
23#include <linux/spinlock.h> 22#include <linux/spinlock.h>
@@ -29,6 +28,7 @@
29#include <asm/udbg.h> 28#include <asm/udbg.h>
30#include <asm/io.h> 29#include <asm/io.h>
31#include <asm/cpm.h> 30#include <asm/cpm.h>
31#include <asm/qe.h>
32 32
33#include <mm/mmu_decl.h> 33#include <mm/mmu_decl.h>
34 34
@@ -65,212 +65,6 @@ void __init udbg_init_cpm(void)
65} 65}
66#endif 66#endif
67 67
68static struct gen_pool *muram_pool;
69static spinlock_t cpm_muram_lock;
70static u8 __iomem *muram_vbase;
71static phys_addr_t muram_pbase;
72
73struct muram_block {
74 struct list_head head;
75 unsigned long start;
76 int size;
77};
78
79static LIST_HEAD(muram_block_list);
80
81/* max address size we deal with */
82#define OF_MAX_ADDR_CELLS 4
83#define GENPOOL_OFFSET (4096 * 8)
84
85int cpm_muram_init(void)
86{
87 struct device_node *np;
88 struct resource r;
89 u32 zero[OF_MAX_ADDR_CELLS] = {};
90 resource_size_t max = 0;
91 int i = 0;
92 int ret = 0;
93
94 if (muram_pbase)
95 return 0;
96
97 spin_lock_init(&cpm_muram_lock);
98 np = of_find_compatible_node(NULL, NULL, "fsl,cpm-muram-data");
99 if (!np) {
100 /* try legacy bindings */
101 np = of_find_node_by_name(NULL, "data-only");
102 if (!np) {
103 pr_err("Cannot find CPM muram data node");
104 ret = -ENODEV;
105 goto out_muram;
106 }
107 }
108
109 muram_pool = gen_pool_create(0, -1);
110 muram_pbase = of_translate_address(np, zero);
111 if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) {
112 pr_err("Cannot translate zero through CPM muram node");
113 ret = -ENODEV;
114 goto out_pool;
115 }
116
117 while (of_address_to_resource(np, i++, &r) == 0) {
118 if (r.end > max)
119 max = r.end;
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 }
126 }
127
128 muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1);
129 if (!muram_vbase) {
130 pr_err("Cannot map QE muram");
131 ret = -ENOMEM;
132 goto out_pool;
133 }
134 goto out_muram;
135out_pool:
136 gen_pool_destroy(muram_pool);
137out_muram:
138 of_node_put(np);
139 return ret;
140}
141
142/*
143 * cpm_muram_alloc - allocate the requested size worth of multi-user ram
144 * @size: number of bytes to allocate
145 * @align: requested alignment, in bytes
146 *
147 * This function returns an offset into the muram area.
148 * Use cpm_dpram_addr() to get the virtual address of the area.
149 * Use cpm_muram_free() to free the allocation.
150 */
151unsigned long cpm_muram_alloc(unsigned long size, unsigned long align)
152{
153 unsigned long start;
154 unsigned long flags;
155 struct genpool_data_align muram_pool_data;
156
157 spin_lock_irqsave(&cpm_muram_lock, flags);
158 muram_pool_data.align = align;
159 start = cpm_muram_alloc_common(size, gen_pool_first_fit_align,
160 &muram_pool_data);
161 spin_unlock_irqrestore(&cpm_muram_lock, flags);
162 return start;
163}
164EXPORT_SYMBOL(cpm_muram_alloc);
165
166/**
167 * cpm_muram_free - free a chunk of multi-user ram
168 * @offset: The beginning of the chunk as returned by cpm_muram_alloc().
169 */
170int cpm_muram_free(unsigned long offset)
171{
172 unsigned long flags;
173 int size;
174 struct muram_block *tmp;
175
176 size = 0;
177 spin_lock_irqsave(&cpm_muram_lock, flags);
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);
187 spin_unlock_irqrestore(&cpm_muram_lock, flags);
188 return size;
189}
190EXPORT_SYMBOL(cpm_muram_free);
191
192/*
193 * cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
194 * @offset: offset of allocation start address
195 * @size: number of bytes to allocate
196 * This function returns an offset into the muram area
197 * Use cpm_dpram_addr() to get the virtual address of the area.
198 * Use cpm_muram_free() to free the allocation.
199 */
200unsigned long cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
201{
202 unsigned long start;
203 unsigned long flags;
204 struct genpool_data_fixed muram_pool_data_fixed;
205
206 spin_lock_irqsave(&cpm_muram_lock, flags);
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);
210 spin_unlock_irqrestore(&cpm_muram_lock, flags);
211 return start;
212}
213EXPORT_SYMBOL(cpm_muram_alloc_fixed);
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 */
223unsigned 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;
242out1:
243 gen_pool_free(muram_pool, start, size);
244out2:
245 return (unsigned long)-ENOMEM;
246}
247
248/**
249 * cpm_muram_addr - turn a muram offset into a virtual address
250 * @offset: muram offset to convert
251 */
252void __iomem *cpm_muram_addr(unsigned long offset)
253{
254 return muram_vbase + offset;
255}
256EXPORT_SYMBOL(cpm_muram_addr);
257
258unsigned long cpm_muram_offset(void __iomem *addr)
259{
260 return addr - (void __iomem *)muram_vbase;
261}
262EXPORT_SYMBOL(cpm_muram_offset);
263
264/**
265 * cpm_muram_dma - turn a muram virtual address into a DMA address
266 * @offset: virtual address from cpm_muram_addr() to convert
267 */
268dma_addr_t cpm_muram_dma(void __iomem *addr)
269{
270 return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
271}
272EXPORT_SYMBOL(cpm_muram_dma);
273
274#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO) 68#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO)
275 69
276struct cpm2_ioports { 70struct cpm2_ioports {