aboutsummaryrefslogtreecommitdiff
path: root/include/lmb.h
blob: 198429113224bd43955e56cc7476110edcb72b03 (plain)
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef _LINUX_LMB_H
#define _LINUX_LMB_H
#ifdef __KERNEL__

#include <asm/types.h>
#include <asm/u-boot.h>

/*
 * Logical memory blocks.
 *
 * Copyright (C) 2001 Peter Bergner, IBM Corp.
 */

/**
 * enum lmb_flags - definition of memory region attributes
 * @LMB_NONE: no special request
 * @LMB_NOMAP: don't add to mmu configuration
 */
enum lmb_flags {
	LMB_NONE		= 0x0,
	LMB_NOMAP		= 0x4,
};

/**
 * struct lmb_property - Description of one region.
 *
 * @base: Base address of the region.
 * @size: Size of the region
 */
struct lmb_property {
	phys_addr_t base;
	phys_size_t size;
	enum lmb_flags flags;
};

/**
 * struct lmb_region - Description of a set of region.
 *
 * @cnt: Number of regions.
 * @max: Size of the region array, max value of cnt.
 * @region: Array of the region properties
 */
struct lmb_region {
	unsigned long cnt;
	unsigned long max;
#if IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
	struct lmb_property region[CONFIG_LMB_MAX_REGIONS];
#else
	struct lmb_property *region;
#endif
};

/**
 * struct lmb - Logical memory block handle.
 *
 * Clients provide storage for Logical memory block (lmb) handles.
 * The content of the structure is managed by the lmb library.
 * A lmb struct is  initialized by lmb_init() functions.
 * The lmb struct is passed to all other lmb APIs.
 *
 * @memory: Description of memory regions.
 * @reserved: Description of reserved regions.
 * @memory_regions: Array of the memory regions (statically allocated)
 * @reserved_regions: Array of the reserved regions (statically allocated)
 */
struct lmb {
	struct lmb_region memory;
	struct lmb_region reserved;
#if !IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS)
	struct lmb_property memory_regions[CONFIG_LMB_MEMORY_REGIONS];
	struct lmb_property reserved_regions[CONFIG_LMB_RESERVED_REGIONS];
#endif
};

extern void lmb_init(struct lmb *lmb);
extern void lmb_init_and_reserve(struct lmb *lmb, struct bd_info *bd,
				 void *fdt_blob);
extern void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base,
				       phys_size_t size, void *fdt_blob);
extern long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size);
extern long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size);
/**
 * lmb_reserve_flags - Reserve one region with a specific flags bitfield.
 *
 * @lmb		the logical memory block struct
 * @base	base address of the memory region
 * @size	size of the memory region
 * @flags	flags for the memory region
 * @return 0 if OK, > 0 for coalesced region or a negative error code.
 */
long lmb_reserve_flags(struct lmb *lmb, phys_addr_t base,
		       phys_size_t size, enum lmb_flags flags);
extern phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align);
extern phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
			    phys_addr_t max_addr);
extern phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
			      phys_addr_t max_addr);
extern phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base,
				  phys_size_t size);
extern phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr);
extern int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr);
/**
 * lmb_is_reserved_flags - test if tha address is in reserved region with a bitfield flag
 *
 * @lmb		the logical memory block struct
 * @addr	address to be tested
 * @flags	flags bitfied to be tested
 * @return 0 if not reserved or reserved without the requested flag else 1
 */
int lmb_is_reserved_flags(struct lmb *lmb, phys_addr_t addr, int flags);
extern long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size);

extern void lmb_dump_all(struct lmb *lmb);
extern void lmb_dump_all_force(struct lmb *lmb);

static inline phys_size_t
lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
{
	return type->region[region_nr].size;
}

void board_lmb_reserve(struct lmb *lmb);
void arch_lmb_reserve(struct lmb *lmb);
void arch_lmb_reserve_generic(struct lmb *lmb, ulong sp, ulong end, ulong align);

/* Low level functions */

static inline bool lmb_is_nomap(struct lmb_property *m)
{
	return m->flags & LMB_NOMAP;
}

#endif /* __KERNEL__ */

#endif /* _LINUX_LMB_H */