1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * PowerPC 4xx OCM memory allocation support
5 * (C) Copyright 2009, Applied Micro Circuits Corporation
6 * Victor Gallardo (vgallardo@amcc.com)
8 * See file CREDITS for list of people who contributed to this
12 #include <linux/kernel.h>
13 #include <linux/dma-mapping.h>
15 #include <linux/of_address.h>
16 #include <asm/rheap.h>
17 #include <asm/ppc4xx_ocm.h>
18 #include <linux/slab.h>
19 #include <linux/debugfs.h>
21 #define OCM_DISABLED 0
25 struct list_head list
;
31 /* non-cached or cached region */
40 struct list_head list
;
54 struct ocm_region nc
; /* non-cached region */
55 struct ocm_region c
; /* cached region */
58 static struct ocm_info
*ocm_nodes
;
61 static struct ocm_info
*ocm_get_node(unsigned int index
)
63 if (index
>= ocm_count
) {
64 printk(KERN_ERR
"PPC4XX OCM: invalid index");
68 return &ocm_nodes
[index
];
71 static int ocm_free_region(struct ocm_region
*ocm_reg
, const void *addr
)
73 struct ocm_block
*blk
, *tmp
;
79 list_for_each_entry_safe(blk
, tmp
, &ocm_reg
->list
, list
) {
80 if (blk
->addr
== addr
) {
81 offset
= addr
- ocm_reg
->virt
;
82 ocm_reg
->memfree
+= blk
->size
;
83 rh_free(ocm_reg
->rh
, offset
);
93 static void __init
ocm_init_node(int count
, struct device_node
*node
)
97 const unsigned int *cell_index
;
98 const unsigned int *cache_size
;
101 struct resource rsrc
;
103 ocm
= ocm_get_node(count
);
105 cell_index
= of_get_property(node
, "cell-index", &len
);
107 printk(KERN_ERR
"PPC4XX OCM: missing cell-index property");
110 ocm
->index
= *cell_index
;
112 if (of_device_is_available(node
))
113 ocm
->status
= OCM_ENABLED
;
115 cache_size
= of_get_property(node
, "cached-region-size", &len
);
117 ocm
->cache_size
= *cache_size
;
119 if (of_address_to_resource(node
, 0, &rsrc
)) {
120 printk(KERN_ERR
"PPC4XX OCM%d: could not get resource address\n",
125 ocm
->phys
= rsrc
.start
;
126 ocm
->memtotal
= (rsrc
.end
- rsrc
.start
+ 1);
128 printk(KERN_INFO
"PPC4XX OCM%d: %d Bytes (%s)\n",
129 ocm
->index
, ocm
->memtotal
,
130 (ocm
->status
== OCM_DISABLED
) ? "disabled" : "enabled");
132 if (ocm
->status
== OCM_DISABLED
)
137 if (!request_mem_region(ocm
->phys
, ocm
->memtotal
, "ppc4xx_ocm")) {
138 printk(KERN_ERR
"PPC4XX OCM%d: could not request region\n",
143 /* Configure non-cached and cached regions */
145 ocm
->nc
.phys
= ocm
->phys
;
146 ocm
->nc
.memtotal
= ocm
->memtotal
- ocm
->cache_size
;
147 ocm
->nc
.memfree
= ocm
->nc
.memtotal
;
149 ocm
->c
.phys
= ocm
->phys
+ ocm
->nc
.memtotal
;
150 ocm
->c
.memtotal
= ocm
->cache_size
;
151 ocm
->c
.memfree
= ocm
->c
.memtotal
;
153 if (ocm
->nc
.memtotal
== 0)
156 if (ocm
->c
.memtotal
== 0)
159 printk(KERN_INFO
"PPC4XX OCM%d: %d Bytes (non-cached)\n",
160 ocm
->index
, ocm
->nc
.memtotal
);
162 printk(KERN_INFO
"PPC4XX OCM%d: %d Bytes (cached)\n",
163 ocm
->index
, ocm
->c
.memtotal
);
165 /* ioremap the non-cached region */
166 if (ocm
->nc
.memtotal
) {
167 ocm
->nc
.virt
= __ioremap(ocm
->nc
.phys
, ocm
->nc
.memtotal
,
168 _PAGE_EXEC
| pgprot_val(PAGE_KERNEL_NCG
));
172 "PPC4XX OCM%d: failed to ioremap non-cached memory\n",
179 /* ioremap the cached region */
181 if (ocm
->c
.memtotal
) {
182 ocm
->c
.virt
= __ioremap(ocm
->c
.phys
, ocm
->c
.memtotal
,
183 _PAGE_EXEC
| pgprot_val(PAGE_KERNEL
));
187 "PPC4XX OCM%d: failed to ioremap cached memory\n",
194 /* Create Remote Heaps */
196 ocm
->alignment
= 4; /* default 4 byte alignment */
199 ocm
->nc
.rh
= rh_create(ocm
->alignment
);
200 rh_attach_region(ocm
->nc
.rh
, 0, ocm
->nc
.memtotal
);
204 ocm
->c
.rh
= rh_create(ocm
->alignment
);
205 rh_attach_region(ocm
->c
.rh
, 0, ocm
->c
.memtotal
);
208 INIT_LIST_HEAD(&ocm
->nc
.list
);
209 INIT_LIST_HEAD(&ocm
->c
.list
);
214 static int ocm_debugfs_show(struct seq_file
*m
, void *v
)
216 struct ocm_block
*blk
, *tmp
;
219 for (i
= 0; i
< ocm_count
; i
++) {
220 struct ocm_info
*ocm
= ocm_get_node(i
);
222 if (!ocm
|| !ocm
->ready
)
225 seq_printf(m
, "PPC4XX OCM : %d\n", ocm
->index
);
226 seq_printf(m
, "PhysAddr : %pa\n", &(ocm
->phys
));
227 seq_printf(m
, "MemTotal : %d Bytes\n", ocm
->memtotal
);
228 seq_printf(m
, "MemTotal(NC) : %d Bytes\n", ocm
->nc
.memtotal
);
229 seq_printf(m
, "MemTotal(C) : %d Bytes\n\n", ocm
->c
.memtotal
);
231 seq_printf(m
, "NC.PhysAddr : %pa\n", &(ocm
->nc
.phys
));
232 seq_printf(m
, "NC.VirtAddr : 0x%p\n", ocm
->nc
.virt
);
233 seq_printf(m
, "NC.MemTotal : %d Bytes\n", ocm
->nc
.memtotal
);
234 seq_printf(m
, "NC.MemFree : %d Bytes\n", ocm
->nc
.memfree
);
236 list_for_each_entry_safe(blk
, tmp
, &ocm
->nc
.list
, list
) {
237 seq_printf(m
, "NC.MemUsed : %d Bytes (%s)\n",
238 blk
->size
, blk
->owner
);
241 seq_printf(m
, "\nC.PhysAddr : %pa\n", &(ocm
->c
.phys
));
242 seq_printf(m
, "C.VirtAddr : 0x%p\n", ocm
->c
.virt
);
243 seq_printf(m
, "C.MemTotal : %d Bytes\n", ocm
->c
.memtotal
);
244 seq_printf(m
, "C.MemFree : %d Bytes\n", ocm
->c
.memfree
);
246 list_for_each_entry_safe(blk
, tmp
, &ocm
->c
.list
, list
) {
247 seq_printf(m
, "C.MemUsed : %d Bytes (%s)\n",
248 blk
->size
, blk
->owner
);
257 static int ocm_debugfs_open(struct inode
*inode
, struct file
*file
)
259 return single_open(file
, ocm_debugfs_show
, NULL
);
262 static const struct file_operations ocm_debugfs_fops
= {
263 .open
= ocm_debugfs_open
,
266 .release
= single_release
,
269 static int ocm_debugfs_init(void)
273 junk
= debugfs_create_dir("ppc4xx_ocm", 0);
275 printk(KERN_ALERT
"debugfs ppc4xx ocm: failed to create dir\n");
279 if (debugfs_create_file("info", 0644, junk
, NULL
, &ocm_debugfs_fops
)) {
280 printk(KERN_ALERT
"debugfs ppc4xx ocm: failed to create file\n");
287 void *ppc4xx_ocm_alloc(phys_addr_t
*phys
, int size
, int align
,
288 int flags
, const char *owner
)
290 void __iomem
*addr
= NULL
;
291 unsigned long offset
;
292 struct ocm_info
*ocm
;
293 struct ocm_region
*ocm_reg
;
294 struct ocm_block
*ocm_blk
;
297 for (i
= 0; i
< ocm_count
; i
++) {
298 ocm
= ocm_get_node(i
);
300 if (!ocm
|| !ocm
->ready
)
303 if (flags
== PPC4XX_OCM_NON_CACHED
)
311 if (align
< ocm
->alignment
)
312 align
= ocm
->alignment
;
314 offset
= rh_alloc_align(ocm_reg
->rh
, size
, align
, NULL
);
316 if (IS_ERR_VALUE(offset
))
319 ocm_blk
= kzalloc(sizeof(*ocm_blk
), GFP_KERNEL
);
321 rh_free(ocm_reg
->rh
, offset
);
325 *phys
= ocm_reg
->phys
+ offset
;
326 addr
= ocm_reg
->virt
+ offset
;
327 size
= ALIGN(size
, align
);
329 ocm_blk
->addr
= addr
;
330 ocm_blk
->size
= size
;
331 ocm_blk
->owner
= owner
;
332 list_add_tail(&ocm_blk
->list
, &ocm_reg
->list
);
334 ocm_reg
->memfree
-= size
;
342 void ppc4xx_ocm_free(const void *addr
)
349 for (i
= 0; i
< ocm_count
; i
++) {
350 struct ocm_info
*ocm
= ocm_get_node(i
);
352 if (!ocm
|| !ocm
->ready
)
355 if (ocm_free_region(&ocm
->nc
, addr
) ||
356 ocm_free_region(&ocm
->c
, addr
))
361 static int __init
ppc4xx_ocm_init(void)
363 struct device_node
*np
;
367 for_each_compatible_node(np
, NULL
, "ibm,ocm")
373 ocm_nodes
= kzalloc((count
* sizeof(struct ocm_info
)), GFP_KERNEL
);
380 for_each_compatible_node(np
, NULL
, "ibm,ocm") {
381 ocm_init_node(count
, np
);
390 arch_initcall(ppc4xx_ocm_init
);