Skip to content

Commit 032a1ec

Browse files
lokeshvutlaMarc Zyngier
authored andcommitted
firmware: ti_sci: Add helper apis to manage resources
Each resource with in the device can be uniquely identified as defined by TISCI. Since this is generic across the devices, resource allocation also can be made generic instead of each client driver handling the resource. So add helper apis to manage the resource. Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com> Acked-by: Nishanth Menon <nm@ti.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
1 parent 754c947 commit 032a1ec

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

drivers/firmware/ti_sci.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,6 +2262,136 @@ const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
22622262
}
22632263
EXPORT_SYMBOL_GPL(devm_ti_sci_get_by_phandle);
22642264

2265+
/**
2266+
* ti_sci_get_free_resource() - Get a free resource from TISCI resource.
2267+
* @res: Pointer to the TISCI resource
2268+
*
2269+
* Return: resource num if all went ok else TI_SCI_RESOURCE_NULL.
2270+
*/
2271+
u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
2272+
{
2273+
unsigned long flags;
2274+
u16 set, free_bit;
2275+
2276+
raw_spin_lock_irqsave(&res->lock, flags);
2277+
for (set = 0; set < res->sets; set++) {
2278+
free_bit = find_first_zero_bit(res->desc[set].res_map,
2279+
res->desc[set].num);
2280+
if (free_bit != res->desc[set].num) {
2281+
set_bit(free_bit, res->desc[set].res_map);
2282+
raw_spin_unlock_irqrestore(&res->lock, flags);
2283+
return res->desc[set].start + free_bit;
2284+
}
2285+
}
2286+
raw_spin_unlock_irqrestore(&res->lock, flags);
2287+
2288+
return TI_SCI_RESOURCE_NULL;
2289+
}
2290+
EXPORT_SYMBOL_GPL(ti_sci_get_free_resource);
2291+
2292+
/**
2293+
* ti_sci_release_resource() - Release a resource from TISCI resource.
2294+
* @res: Pointer to the TISCI resource
2295+
* @id: Resource id to be released.
2296+
*/
2297+
void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
2298+
{
2299+
unsigned long flags;
2300+
u16 set;
2301+
2302+
raw_spin_lock_irqsave(&res->lock, flags);
2303+
for (set = 0; set < res->sets; set++) {
2304+
if (res->desc[set].start <= id &&
2305+
(res->desc[set].num + res->desc[set].start) > id)
2306+
clear_bit(id - res->desc[set].start,
2307+
res->desc[set].res_map);
2308+
}
2309+
raw_spin_unlock_irqrestore(&res->lock, flags);
2310+
}
2311+
EXPORT_SYMBOL_GPL(ti_sci_release_resource);
2312+
2313+
/**
2314+
* ti_sci_get_num_resources() - Get the number of resources in TISCI resource
2315+
* @res: Pointer to the TISCI resource
2316+
*
2317+
* Return: Total number of available resources.
2318+
*/
2319+
u32 ti_sci_get_num_resources(struct ti_sci_resource *res)
2320+
{
2321+
u32 set, count = 0;
2322+
2323+
for (set = 0; set < res->sets; set++)
2324+
count += res->desc[set].num;
2325+
2326+
return count;
2327+
}
2328+
EXPORT_SYMBOL_GPL(ti_sci_get_num_resources);
2329+
2330+
/**
2331+
* devm_ti_sci_get_of_resource() - Get a TISCI resource assigned to a device
2332+
* @handle: TISCI handle
2333+
* @dev: Device pointer to which the resource is assigned
2334+
* @dev_id: TISCI device id to which the resource is assigned
2335+
* @of_prop: property name by which the resource are represented
2336+
*
2337+
* Return: Pointer to ti_sci_resource if all went well else appropriate
2338+
* error pointer.
2339+
*/
2340+
struct ti_sci_resource *
2341+
devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
2342+
struct device *dev, u32 dev_id, char *of_prop)
2343+
{
2344+
struct ti_sci_resource *res;
2345+
u32 resource_subtype;
2346+
int i, ret;
2347+
2348+
res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
2349+
if (!res)
2350+
return ERR_PTR(-ENOMEM);
2351+
2352+
res->sets = of_property_count_elems_of_size(dev_of_node(dev), of_prop,
2353+
sizeof(u32));
2354+
if (res->sets < 0) {
2355+
dev_err(dev, "%s resource type ids not available\n", of_prop);
2356+
return ERR_PTR(res->sets);
2357+
}
2358+
2359+
res->desc = devm_kcalloc(dev, res->sets, sizeof(*res->desc),
2360+
GFP_KERNEL);
2361+
if (!res->desc)
2362+
return ERR_PTR(-ENOMEM);
2363+
2364+
for (i = 0; i < res->sets; i++) {
2365+
ret = of_property_read_u32_index(dev_of_node(dev), of_prop, i,
2366+
&resource_subtype);
2367+
if (ret)
2368+
return ERR_PTR(-EINVAL);
2369+
2370+
ret = handle->ops.rm_core_ops.get_range(handle, dev_id,
2371+
resource_subtype,
2372+
&res->desc[i].start,
2373+
&res->desc[i].num);
2374+
if (ret) {
2375+
dev_err(dev, "dev = %d subtype %d not allocated for this host\n",
2376+
dev_id, resource_subtype);
2377+
return ERR_PTR(ret);
2378+
}
2379+
2380+
dev_dbg(dev, "dev = %d, subtype = %d, start = %d, num = %d\n",
2381+
dev_id, resource_subtype, res->desc[i].start,
2382+
res->desc[i].num);
2383+
2384+
res->desc[i].res_map =
2385+
devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) *
2386+
sizeof(*res->desc[i].res_map), GFP_KERNEL);
2387+
if (!res->desc[i].res_map)
2388+
return ERR_PTR(-ENOMEM);
2389+
}
2390+
raw_spin_lock_init(&res->lock);
2391+
2392+
return res;
2393+
}
2394+
22652395
static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode,
22662396
void *cmd)
22672397
{

include/linux/soc/ti/ti_sci_protocol.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,33 @@ struct ti_sci_handle {
266266
struct ti_sci_ops ops;
267267
};
268268

269+
#define TI_SCI_RESOURCE_NULL 0xffff
270+
271+
/**
272+
* struct ti_sci_resource_desc - Description of TI SCI resource instance range.
273+
* @start: Start index of the resource.
274+
* @num: Number of resources.
275+
* @res_map: Bitmap to manage the allocation of these resources.
276+
*/
277+
struct ti_sci_resource_desc {
278+
u16 start;
279+
u16 num;
280+
unsigned long *res_map;
281+
};
282+
283+
/**
284+
* struct ti_sci_resource - Structure representing a resource assigned
285+
* to a device.
286+
* @sets: Number of sets available from this resource type
287+
* @lock: Lock to guard the res map in each set.
288+
* @desc: Array of resource descriptors.
289+
*/
290+
struct ti_sci_resource {
291+
u16 sets;
292+
raw_spinlock_t lock;
293+
struct ti_sci_resource_desc *desc;
294+
};
295+
269296
#if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL)
270297
const struct ti_sci_handle *ti_sci_get_handle(struct device *dev);
271298
int ti_sci_put_handle(const struct ti_sci_handle *handle);
@@ -274,6 +301,12 @@ const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
274301
const char *property);
275302
const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
276303
const char *property);
304+
u16 ti_sci_get_free_resource(struct ti_sci_resource *res);
305+
void ti_sci_release_resource(struct ti_sci_resource *res, u16 id);
306+
u32 ti_sci_get_num_resources(struct ti_sci_resource *res);
307+
struct ti_sci_resource *
308+
devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
309+
struct device *dev, u32 dev_id, char *of_prop);
277310

278311
#else /* CONFIG_TI_SCI_PROTOCOL */
279312

@@ -306,6 +339,27 @@ const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
306339
{
307340
return ERR_PTR(-EINVAL);
308341
}
342+
343+
static inline u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
344+
{
345+
return TI_SCI_RESOURCE_NULL;
346+
}
347+
348+
static inline void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
349+
{
350+
}
351+
352+
static inline u32 ti_sci_get_num_resources(struct ti_sci_resource *res)
353+
{
354+
return 0;
355+
}
356+
357+
static inline struct ti_sci_resource *
358+
devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle,
359+
struct device *dev, u32 dev_id, char *of_prop)
360+
{
361+
return ERR_PTR(-EINVAL);
362+
}
309363
#endif /* CONFIG_TI_SCI_PROTOCOL */
310364

311365
#endif /* __TISCI_PROTOCOL_H */

0 commit comments

Comments
 (0)