blob: f221f0cce8f76819686f9949e89ba12fd84c627c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
Kumar Gala6d7bfa82008-02-27 21:51:47 -06002#ifndef _LINUX_LMB_H
3#define _LINUX_LMB_H
4#ifdef __KERNEL__
5
Sughosh Ganu291bf9c2024-08-26 17:29:18 +05306#include <alist.h>
Kumar Gala6d7bfa82008-02-27 21:51:47 -06007#include <asm/types.h>
Simon Goldschmidt8890e7d2019-01-26 22:13:04 +01008#include <asm/u-boot.h>
Sughosh Ganu26d7fa12024-08-26 17:29:17 +05309#include <linux/bitops.h>
Simon Goldschmidt8890e7d2019-01-26 22:13:04 +010010
Kumar Gala6d7bfa82008-02-27 21:51:47 -060011/*
12 * Logical memory blocks.
13 *
14 * Copyright (C) 2001 Peter Bergner, IBM Corp.
Kumar Gala6d7bfa82008-02-27 21:51:47 -060015 */
16
Ilias Apalodimas7d182fb2024-10-23 18:26:36 +030017#define LMB_ALLOC_ANYWHERE 0
18#define LMB_ALIST_INITIAL_SIZE 4
19
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010020/**
Patrick Delaunaye11c9082021-05-07 14:50:29 +020021 * enum lmb_flags - definition of memory region attributes
22 * @LMB_NONE: no special request
23 * @LMB_NOMAP: don't add to mmu configuration
Sughosh Ganu7ebbdd72024-10-15 21:07:04 +053024 * @LMB_NOOVERWRITE: the memory region cannot be overwritten/re-reserved
25 * @LMB_NONOTIFY: do not notify other modules of changes to this memory region
Patrick Delaunaye11c9082021-05-07 14:50:29 +020026 */
27enum lmb_flags {
Sughosh Ganu26d7fa12024-08-26 17:29:17 +053028 LMB_NONE = 0,
29 LMB_NOMAP = BIT(1),
Sughosh Ganu50e27272024-08-26 17:29:19 +053030 LMB_NOOVERWRITE = BIT(2),
Sughosh Ganu7ebbdd72024-10-15 21:07:04 +053031 LMB_NONOTIFY = BIT(3),
Patrick Delaunaye11c9082021-05-07 14:50:29 +020032};
33
34/**
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053035 * struct lmb_region - Description of one region.
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010036 *
Heinrich Schuchardte6923f02021-11-14 08:43:07 +010037 * @base: Base address of the region.
38 * @size: Size of the region
39 * @flags: memory region attributes
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010040 */
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053041struct lmb_region {
Becky Bruced26d67c2008-06-09 20:37:18 -050042 phys_addr_t base;
43 phys_size_t size;
Patrick Delaunaye11c9082021-05-07 14:50:29 +020044 enum lmb_flags flags;
Kumar Gala6d7bfa82008-02-27 21:51:47 -060045};
46
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010047/**
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053048 * struct lmb - The LMB structure
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010049 *
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053050 * @free_mem: List of free memory regions
51 * @used_mem: List of used/reserved memory regions
Sughosh Ganua3af5ba2024-10-15 21:07:07 +053052 * @test: Is structure being used for LMB tests
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010053 */
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053054struct lmb {
55 struct alist free_mem;
56 struct alist used_mem;
Sughosh Ganua3af5ba2024-10-15 21:07:07 +053057 bool test;
Kumar Gala6d7bfa82008-02-27 21:51:47 -060058};
59
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010060/**
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053061 * lmb_init() - Initialise the LMB module
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010062 *
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053063 * Initialise the LMB lists needed for keeping the memory map. There
64 * are two lists, in form of alloced list data structure. One for the
65 * available memory, and one for the used memory. Initialise the two
66 * lists as part of board init. Add memory to the available memory
67 * list and reserve common areas by adding them to the used memory
68 * list.
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010069 *
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053070 * Return: 0 on success, -ve on error
Patrick Delaunay71cc9c52021-03-10 10:16:31 +010071 */
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053072int lmb_init(void);
Kumar Gala6d7bfa82008-02-27 21:51:47 -060073
Sughosh Ganu65597fa2024-08-26 17:29:23 +053074/**
75 * lmb_add_memory() - Add memory range for LMB allocations
76 *
77 * Add the entire available memory range to the pool of memory that
78 * can be used by the LMB module for allocations.
79 *
80 * Return: None
81 */
82void lmb_add_memory(void);
83
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053084long lmb_add(phys_addr_t base, phys_size_t size);
85long lmb_reserve(phys_addr_t base, phys_size_t size);
Patrick Delaunaye11c9082021-05-07 14:50:29 +020086/**
87 * lmb_reserve_flags - Reserve one region with a specific flags bitfield.
88 *
Heinrich Schuchardte6923f02021-11-14 08:43:07 +010089 * @base: base address of the memory region
90 * @size: size of the memory region
91 * @flags: flags for the memory region
92 * Return: 0 if OK, > 0 for coalesced region or a negative error code.
Patrick Delaunaye11c9082021-05-07 14:50:29 +020093 */
Sughosh Ganu291bf9c2024-08-26 17:29:18 +053094long lmb_reserve_flags(phys_addr_t base, phys_size_t size,
95 enum lmb_flags flags);
96phys_addr_t lmb_alloc(phys_size_t size, ulong align);
97phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr);
98phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t size);
99phys_size_t lmb_get_free_size(phys_addr_t addr);
Heinrich Schuchardt5411fb72023-08-12 19:09:32 +0200100
Sughosh Ganu7f15d322024-10-15 21:07:03 +0530101phys_addr_t lmb_alloc_base_flags(phys_size_t size, ulong align,
102 phys_addr_t max_addr, uint flags);
103
104/**
105 * lmb_alloc_addr_flags() - Allocate specified memory address with specified attributes
106 * @base: Base Address requested
107 * @size: Size of the region requested
108 * @flags: Memory region attributes to be set
109 *
110 * Allocate a region of memory with the attributes specified through the
111 * parameter. The base parameter is used to specify the base address
112 * of the requested region.
113 *
114 * Return: base address on success, 0 on error
115 */
116phys_addr_t lmb_alloc_addr_flags(phys_addr_t base, phys_size_t size,
117 uint flags);
118
119/**
Heinrich Schuchardt5411fb72023-08-12 19:09:32 +0200120 * lmb_is_reserved_flags() - test if address is in reserved region with flag bits set
121 *
122 * The function checks if a reserved region comprising @addr exists which has
123 * all flag bits set which are set in @flags.
Patrick Delaunaydb2c9aa2021-05-07 14:50:30 +0200124 *
Heinrich Schuchardte6923f02021-11-14 08:43:07 +0100125 * @addr: address to be tested
Heinrich Schuchardt5411fb72023-08-12 19:09:32 +0200126 * @flags: bitmap with bits to be tested
127 * Return: 1 if matching reservation exists, 0 otherwise
Patrick Delaunaydb2c9aa2021-05-07 14:50:30 +0200128 */
Sughosh Ganu291bf9c2024-08-26 17:29:18 +0530129int lmb_is_reserved_flags(phys_addr_t addr, int flags);
Heinrich Schuchardt5411fb72023-08-12 19:09:32 +0200130
Sughosh Ganu7f15d322024-10-15 21:07:03 +0530131/**
132 * lmb_free_flags() - Free up a region of memory
133 * @base: Base Address of region to be freed
134 * @size: Size of the region to be freed
135 * @flags: Memory region attributes
136 *
137 * Free up a region of memory.
138 *
139 * Return: 0 if successful, -1 on failure
140 */
141long lmb_free_flags(phys_addr_t base, phys_size_t size, uint flags);
142
Sughosh Ganu291bf9c2024-08-26 17:29:18 +0530143long lmb_free(phys_addr_t base, phys_size_t size);
Kumar Gala6d7bfa82008-02-27 21:51:47 -0600144
Sughosh Ganu291bf9c2024-08-26 17:29:18 +0530145void lmb_dump_all(void);
146void lmb_dump_all_force(void);
147
Sughosh Ganu1a36d442024-10-15 21:07:11 +0530148void lmb_arch_add_memory(void);
149
Sughosh Ganu291bf9c2024-08-26 17:29:18 +0530150struct lmb *lmb_get(void);
151int lmb_push(struct lmb *store);
152void lmb_pop(struct lmb *store);
Mike Frysingera0dadf82009-11-03 11:35:59 -0500153
Prasad Kummari940bebc2024-09-13 13:02:52 +0530154static inline int lmb_read_check(phys_addr_t addr, phys_size_t len)
155{
156 return lmb_alloc_addr(addr, len) == addr ? 0 : -1;
157}
158
Janne Grunaue818d3c2024-11-11 07:56:33 +0100159/**
160 * io_lmb_setup() - Initialize LMB struct
Tom Rinid32dddb2024-11-11 07:26:50 -0600161 * @io_lmb: IO LMB to initialize
Janne Grunaue818d3c2024-11-11 07:56:33 +0100162 *
163 * Returns: 0 on success, negative error code on failure
164 */
165int io_lmb_setup(struct lmb *io_lmb);
166
167/**
168 * io_lmb_teardown() - Tear LMB struct down
Tom Rinid32dddb2024-11-11 07:26:50 -0600169 * @io_lmb: IO LMB to teardown
Janne Grunaue818d3c2024-11-11 07:56:33 +0100170 */
171void io_lmb_teardown(struct lmb *io_lmb);
172
173/**
174 * io_lmb_add() - Add an IOVA range for allocations
175 * @io_lmb: LMB to add the space to
176 * @base: Base Address of region to add
177 * @size: Size of the region to add
178 *
179 * Add the IOVA space [base, base + size] to be managed by io_lmb.
180 *
181 * Returns: 0 if the region addition was successful, -1 on failure
182 */
183long io_lmb_add(struct lmb *io_lmb, phys_addr_t base, phys_size_t size);
184
185/**
186 * io_lmb_alloc() - Allocate specified IO memory address with specified alignment
187 * @io_lmb: LMB to alloc from
188 * @size: Size of the region requested
189 * @align: Required address and size alignment
190 *
191 * Allocate a region of IO memory. The base parameter is used to specify the
192 * base address of the requested region.
193 *
194 * Return: base IO address on success, 0 on error
195 */
196phys_addr_t io_lmb_alloc(struct lmb *io_lmb, phys_size_t size, ulong align);
197
198/**
199 * io_lmb_free() - Free up a region of IOVA space
200 * @io_lmb: LMB to return the IO address space to
201 * @base: Base Address of region to be freed
202 * @size: Size of the region to be freed
203 *
204 * Free up a region of IOVA space.
205 *
206 * Return: 0 if successful, -1 on failure
207 */
208long io_lmb_free(struct lmb *io_lmb, phys_addr_t base, phys_size_t size);
209
Kumar Gala6d7bfa82008-02-27 21:51:47 -0600210#endif /* __KERNEL__ */
211
212#endif /* _LINUX_LMB_H */