1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: 2005 Jes Sorensen <jes@trained-monkey.org>
/*
* Basic general purpose allocator for managing special purpose
* memory, for example, memory that is not managed by the regular
* kmalloc/kfree interface. Uses for this includes on-device special
* memory, uncached memory etc.
*/
#include <io.h>
#include <linux/ioport.h>
#include <linux/genalloc.h>
#include <linux/export.h>
#include <of.h>
#include <of_address.h>
#include <driver.h>
#include <linux/string.h>
struct gen_pool {
struct resource res;
};
#define res_to_gen_pool(res) \
container_of(res, struct gen_pool, res)
/**
* gen_pool_virt_to_phys - return the physical address of memory
* @pool: pool to allocate from
* @addr: starting address of memory
*
* Returns the physical address on success, or -1 on error.
*/
phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr)
{
return virt_to_phys((void *)addr);
}
EXPORT_SYMBOL(gen_pool_virt_to_phys);
/**
* gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
* @pool: pool to allocate from
* @size: number of bytes to allocate from the pool
* @dma: dma-view physical address return value. Use %NULL if unneeded.
*
* Allocate the requested number of bytes from the specified pool.
* Uses the pool allocation function (with first-fit algorithm by default).
* Can not be used in NMI handler on architectures without
* NMI-safe cmpxchg implementation.
*
* Return: virtual address of the allocated memory, or %NULL on failure
*/
void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
{
unsigned long vaddr;
if (!pool || resource_size(&pool->res) != size)
return NULL;
vaddr = pool->res.start;
if (dma)
*dma = gen_pool_virt_to_phys(pool, vaddr);
return (void *)vaddr;
}
EXPORT_SYMBOL(gen_pool_dma_alloc);
/**
* gen_pool_dma_zalloc - allocate special zeroed memory from the pool for
* DMA usage
* @pool: pool to allocate from
* @size: number of bytes to allocate from the pool
* @dma: dma-view physical address return value. Use %NULL if unneeded.
*
* Return: virtual address of the allocated zeroed memory, or %NULL on failure
*/
void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
{
void *vaddr = gen_pool_dma_alloc(pool, size, dma);
if (vaddr)
memset(vaddr, 0, size);
return vaddr;
}
EXPORT_SYMBOL(gen_pool_dma_zalloc);
#ifdef CONFIG_OFDEVICE
/**
* of_gen_pool_get - find a pool by phandle property
* @np: device node
* @propname: property name containing phandle(s)
* @index: index into the phandle array
*
* Returns the pool that contains the chunk starting at the physical
* address of the device tree node pointed at by the phandle property,
* or NULL if not found.
*/
struct gen_pool *of_gen_pool_get(struct device_node *np,
const char *propname, int index)
{
struct device_node *np_pool;
struct gen_pool gen_pool;
int ret;
np_pool = of_parse_phandle(np, propname, index);
if (!np_pool)
return NULL;
if (!of_device_is_compatible(np_pool, "mmio-sram"))
return NULL;
ret = of_address_to_resource(np_pool, 0, &gen_pool.res);
if (ret)
return NULL;
return memdup(&gen_pool, sizeof(gen_pool));
}
EXPORT_SYMBOL_GPL(of_gen_pool_get);
#endif /* CONFIG_OF */
|