18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * fsl-mc object allocator driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/msi.h>
118c2ecf20Sopenharmony_ci#include <linux/fsl/mc.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "fsl-mc-private.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic bool __must_check fsl_mc_is_allocatable(struct fsl_mc_device *mc_dev)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	return is_fsl_mc_bus_dpbp(mc_dev) ||
188c2ecf20Sopenharmony_ci	       is_fsl_mc_bus_dpmcp(mc_dev) ||
198c2ecf20Sopenharmony_ci	       is_fsl_mc_bus_dpcon(mc_dev);
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/**
238c2ecf20Sopenharmony_ci * fsl_mc_resource_pool_add_device - add allocatable object to a resource
248c2ecf20Sopenharmony_ci * pool of a given fsl-mc bus
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * @mc_bus: pointer to the fsl-mc bus
278c2ecf20Sopenharmony_ci * @pool_type: pool type
288c2ecf20Sopenharmony_ci * @mc_dev: pointer to allocatable fsl-mc device
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_cistatic int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
318c2ecf20Sopenharmony_ci								*mc_bus,
328c2ecf20Sopenharmony_ci							enum fsl_mc_pool_type
338c2ecf20Sopenharmony_ci								pool_type,
348c2ecf20Sopenharmony_ci							struct fsl_mc_device
358c2ecf20Sopenharmony_ci								*mc_dev)
368c2ecf20Sopenharmony_ci{
378c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool;
388c2ecf20Sopenharmony_ci	struct fsl_mc_resource *resource;
398c2ecf20Sopenharmony_ci	struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
408c2ecf20Sopenharmony_ci	int error = -EINVAL;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
438c2ecf20Sopenharmony_ci		goto out;
448c2ecf20Sopenharmony_ci	if (!fsl_mc_is_allocatable(mc_dev))
458c2ecf20Sopenharmony_ci		goto out;
468c2ecf20Sopenharmony_ci	if (mc_dev->resource)
478c2ecf20Sopenharmony_ci		goto out;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	res_pool = &mc_bus->resource_pools[pool_type];
508c2ecf20Sopenharmony_ci	if (res_pool->type != pool_type)
518c2ecf20Sopenharmony_ci		goto out;
528c2ecf20Sopenharmony_ci	if (res_pool->mc_bus != mc_bus)
538c2ecf20Sopenharmony_ci		goto out;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	mutex_lock(&res_pool->mutex);
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	if (res_pool->max_count < 0)
588c2ecf20Sopenharmony_ci		goto out_unlock;
598c2ecf20Sopenharmony_ci	if (res_pool->free_count < 0 ||
608c2ecf20Sopenharmony_ci	    res_pool->free_count > res_pool->max_count)
618c2ecf20Sopenharmony_ci		goto out_unlock;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
648c2ecf20Sopenharmony_ci				GFP_KERNEL);
658c2ecf20Sopenharmony_ci	if (!resource) {
668c2ecf20Sopenharmony_ci		error = -ENOMEM;
678c2ecf20Sopenharmony_ci		dev_err(&mc_bus_dev->dev,
688c2ecf20Sopenharmony_ci			"Failed to allocate memory for fsl_mc_resource\n");
698c2ecf20Sopenharmony_ci		goto out_unlock;
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	resource->type = pool_type;
738c2ecf20Sopenharmony_ci	resource->id = mc_dev->obj_desc.id;
748c2ecf20Sopenharmony_ci	resource->data = mc_dev;
758c2ecf20Sopenharmony_ci	resource->parent_pool = res_pool;
768c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&resource->node);
778c2ecf20Sopenharmony_ci	list_add_tail(&resource->node, &res_pool->free_list);
788c2ecf20Sopenharmony_ci	mc_dev->resource = resource;
798c2ecf20Sopenharmony_ci	res_pool->free_count++;
808c2ecf20Sopenharmony_ci	res_pool->max_count++;
818c2ecf20Sopenharmony_ci	error = 0;
828c2ecf20Sopenharmony_ciout_unlock:
838c2ecf20Sopenharmony_ci	mutex_unlock(&res_pool->mutex);
848c2ecf20Sopenharmony_ciout:
858c2ecf20Sopenharmony_ci	return error;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/**
898c2ecf20Sopenharmony_ci * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
908c2ecf20Sopenharmony_ci * resource pool
918c2ecf20Sopenharmony_ci *
928c2ecf20Sopenharmony_ci * @mc_dev: pointer to allocatable fsl-mc device
938c2ecf20Sopenharmony_ci *
948c2ecf20Sopenharmony_ci * It permanently removes an allocatable fsl-mc device from the resource
958c2ecf20Sopenharmony_ci * pool. It's an error if the device is in use.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_cistatic int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
988c2ecf20Sopenharmony_ci								   *mc_dev)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	struct fsl_mc_device *mc_bus_dev;
1018c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus;
1028c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool;
1038c2ecf20Sopenharmony_ci	struct fsl_mc_resource *resource;
1048c2ecf20Sopenharmony_ci	int error = -EINVAL;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	if (!fsl_mc_is_allocatable(mc_dev))
1078c2ecf20Sopenharmony_ci		goto out;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	resource = mc_dev->resource;
1108c2ecf20Sopenharmony_ci	if (!resource || resource->data != mc_dev)
1118c2ecf20Sopenharmony_ci		goto out;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
1148c2ecf20Sopenharmony_ci	mc_bus = to_fsl_mc_bus(mc_bus_dev);
1158c2ecf20Sopenharmony_ci	res_pool = resource->parent_pool;
1168c2ecf20Sopenharmony_ci	if (res_pool != &mc_bus->resource_pools[resource->type])
1178c2ecf20Sopenharmony_ci		goto out;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	mutex_lock(&res_pool->mutex);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	if (res_pool->max_count <= 0)
1228c2ecf20Sopenharmony_ci		goto out_unlock;
1238c2ecf20Sopenharmony_ci	if (res_pool->free_count <= 0 ||
1248c2ecf20Sopenharmony_ci	    res_pool->free_count > res_pool->max_count)
1258c2ecf20Sopenharmony_ci		goto out_unlock;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	/*
1288c2ecf20Sopenharmony_ci	 * If the device is currently allocated, its resource is not
1298c2ecf20Sopenharmony_ci	 * in the free list and thus, the device cannot be removed.
1308c2ecf20Sopenharmony_ci	 */
1318c2ecf20Sopenharmony_ci	if (list_empty(&resource->node)) {
1328c2ecf20Sopenharmony_ci		error = -EBUSY;
1338c2ecf20Sopenharmony_ci		dev_err(&mc_bus_dev->dev,
1348c2ecf20Sopenharmony_ci			"Device %s cannot be removed from resource pool\n",
1358c2ecf20Sopenharmony_ci			dev_name(&mc_dev->dev));
1368c2ecf20Sopenharmony_ci		goto out_unlock;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	list_del_init(&resource->node);
1408c2ecf20Sopenharmony_ci	res_pool->free_count--;
1418c2ecf20Sopenharmony_ci	res_pool->max_count--;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	devm_kfree(&mc_bus_dev->dev, resource);
1448c2ecf20Sopenharmony_ci	mc_dev->resource = NULL;
1458c2ecf20Sopenharmony_ci	error = 0;
1468c2ecf20Sopenharmony_ciout_unlock:
1478c2ecf20Sopenharmony_ci	mutex_unlock(&res_pool->mutex);
1488c2ecf20Sopenharmony_ciout:
1498c2ecf20Sopenharmony_ci	return error;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic const char *const fsl_mc_pool_type_strings[] = {
1538c2ecf20Sopenharmony_ci	[FSL_MC_POOL_DPMCP] = "dpmcp",
1548c2ecf20Sopenharmony_ci	[FSL_MC_POOL_DPBP] = "dpbp",
1558c2ecf20Sopenharmony_ci	[FSL_MC_POOL_DPCON] = "dpcon",
1568c2ecf20Sopenharmony_ci	[FSL_MC_POOL_IRQ] = "irq",
1578c2ecf20Sopenharmony_ci};
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_cistatic int __must_check object_type_to_pool_type(const char *object_type,
1608c2ecf20Sopenharmony_ci						 enum fsl_mc_pool_type
1618c2ecf20Sopenharmony_ci								*pool_type)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	unsigned int i;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
1668c2ecf20Sopenharmony_ci		if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
1678c2ecf20Sopenharmony_ci			*pool_type = i;
1688c2ecf20Sopenharmony_ci			return 0;
1698c2ecf20Sopenharmony_ci		}
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	return -EINVAL;
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ciint __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
1768c2ecf20Sopenharmony_ci					  enum fsl_mc_pool_type pool_type,
1778c2ecf20Sopenharmony_ci					  struct fsl_mc_resource **new_resource)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool;
1808c2ecf20Sopenharmony_ci	struct fsl_mc_resource *resource;
1818c2ecf20Sopenharmony_ci	struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
1828c2ecf20Sopenharmony_ci	int error = -EINVAL;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
1858c2ecf20Sopenharmony_ci		     FSL_MC_NUM_POOL_TYPES);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	*new_resource = NULL;
1888c2ecf20Sopenharmony_ci	if (pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES)
1898c2ecf20Sopenharmony_ci		goto out;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	res_pool = &mc_bus->resource_pools[pool_type];
1928c2ecf20Sopenharmony_ci	if (res_pool->mc_bus != mc_bus)
1938c2ecf20Sopenharmony_ci		goto out;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	mutex_lock(&res_pool->mutex);
1968c2ecf20Sopenharmony_ci	resource = list_first_entry_or_null(&res_pool->free_list,
1978c2ecf20Sopenharmony_ci					    struct fsl_mc_resource, node);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (!resource) {
2008c2ecf20Sopenharmony_ci		error = -ENXIO;
2018c2ecf20Sopenharmony_ci		dev_err(&mc_bus_dev->dev,
2028c2ecf20Sopenharmony_ci			"No more resources of type %s left\n",
2038c2ecf20Sopenharmony_ci			fsl_mc_pool_type_strings[pool_type]);
2048c2ecf20Sopenharmony_ci		goto out_unlock;
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	if (resource->type != pool_type)
2088c2ecf20Sopenharmony_ci		goto out_unlock;
2098c2ecf20Sopenharmony_ci	if (resource->parent_pool != res_pool)
2108c2ecf20Sopenharmony_ci		goto out_unlock;
2118c2ecf20Sopenharmony_ci	if (res_pool->free_count <= 0 ||
2128c2ecf20Sopenharmony_ci	    res_pool->free_count > res_pool->max_count)
2138c2ecf20Sopenharmony_ci		goto out_unlock;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	list_del_init(&resource->node);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	res_pool->free_count--;
2188c2ecf20Sopenharmony_ci	error = 0;
2198c2ecf20Sopenharmony_ciout_unlock:
2208c2ecf20Sopenharmony_ci	mutex_unlock(&res_pool->mutex);
2218c2ecf20Sopenharmony_ci	*new_resource = resource;
2228c2ecf20Sopenharmony_ciout:
2238c2ecf20Sopenharmony_ci	return error;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_civoid fsl_mc_resource_free(struct fsl_mc_resource *resource)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	res_pool = resource->parent_pool;
2328c2ecf20Sopenharmony_ci	if (resource->type != res_pool->type)
2338c2ecf20Sopenharmony_ci		return;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	mutex_lock(&res_pool->mutex);
2368c2ecf20Sopenharmony_ci	if (res_pool->free_count < 0 ||
2378c2ecf20Sopenharmony_ci	    res_pool->free_count >= res_pool->max_count)
2388c2ecf20Sopenharmony_ci		goto out_unlock;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (!list_empty(&resource->node))
2418c2ecf20Sopenharmony_ci		goto out_unlock;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	list_add_tail(&resource->node, &res_pool->free_list);
2448c2ecf20Sopenharmony_ci	res_pool->free_count++;
2458c2ecf20Sopenharmony_ciout_unlock:
2468c2ecf20Sopenharmony_ci	mutex_unlock(&res_pool->mutex);
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_resource_free);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci/**
2518c2ecf20Sopenharmony_ci * fsl_mc_object_allocate - Allocates an fsl-mc object of the given
2528c2ecf20Sopenharmony_ci * pool type from a given fsl-mc bus instance
2538c2ecf20Sopenharmony_ci *
2548c2ecf20Sopenharmony_ci * @mc_dev: fsl-mc device which is used in conjunction with the
2558c2ecf20Sopenharmony_ci * allocated object
2568c2ecf20Sopenharmony_ci * @pool_type: pool type
2578c2ecf20Sopenharmony_ci * @new_mc_dev: pointer to area where the pointer to the allocated device
2588c2ecf20Sopenharmony_ci * is to be returned
2598c2ecf20Sopenharmony_ci *
2608c2ecf20Sopenharmony_ci * Allocatable objects are always used in conjunction with some functional
2618c2ecf20Sopenharmony_ci * device.  This function allocates an object of the specified type from
2628c2ecf20Sopenharmony_ci * the DPRC containing the functional device.
2638c2ecf20Sopenharmony_ci *
2648c2ecf20Sopenharmony_ci * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
2658c2ecf20Sopenharmony_ci * portals are allocated using fsl_mc_portal_allocate(), instead of
2668c2ecf20Sopenharmony_ci * this function.
2678c2ecf20Sopenharmony_ci */
2688c2ecf20Sopenharmony_ciint __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
2698c2ecf20Sopenharmony_ci					enum fsl_mc_pool_type pool_type,
2708c2ecf20Sopenharmony_ci					struct fsl_mc_device **new_mc_adev)
2718c2ecf20Sopenharmony_ci{
2728c2ecf20Sopenharmony_ci	struct fsl_mc_device *mc_bus_dev;
2738c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus;
2748c2ecf20Sopenharmony_ci	struct fsl_mc_device *mc_adev;
2758c2ecf20Sopenharmony_ci	int error = -EINVAL;
2768c2ecf20Sopenharmony_ci	struct fsl_mc_resource *resource = NULL;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	*new_mc_adev = NULL;
2798c2ecf20Sopenharmony_ci	if (mc_dev->flags & FSL_MC_IS_DPRC)
2808c2ecf20Sopenharmony_ci		goto error;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	if (!dev_is_fsl_mc(mc_dev->dev.parent))
2838c2ecf20Sopenharmony_ci		goto error;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	if (pool_type == FSL_MC_POOL_DPMCP)
2868c2ecf20Sopenharmony_ci		goto error;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
2898c2ecf20Sopenharmony_ci	mc_bus = to_fsl_mc_bus(mc_bus_dev);
2908c2ecf20Sopenharmony_ci	error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
2918c2ecf20Sopenharmony_ci	if (error < 0)
2928c2ecf20Sopenharmony_ci		goto error;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	mc_adev = resource->data;
2958c2ecf20Sopenharmony_ci	if (!mc_adev) {
2968c2ecf20Sopenharmony_ci		error = -EINVAL;
2978c2ecf20Sopenharmony_ci		goto error;
2988c2ecf20Sopenharmony_ci	}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	mc_adev->consumer_link = device_link_add(&mc_dev->dev,
3018c2ecf20Sopenharmony_ci						 &mc_adev->dev,
3028c2ecf20Sopenharmony_ci						 DL_FLAG_AUTOREMOVE_CONSUMER);
3038c2ecf20Sopenharmony_ci	if (!mc_adev->consumer_link) {
3048c2ecf20Sopenharmony_ci		error = -EINVAL;
3058c2ecf20Sopenharmony_ci		goto error;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	*new_mc_adev = mc_adev;
3098c2ecf20Sopenharmony_ci	return 0;
3108c2ecf20Sopenharmony_cierror:
3118c2ecf20Sopenharmony_ci	if (resource)
3128c2ecf20Sopenharmony_ci		fsl_mc_resource_free(resource);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	return error;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci/**
3198c2ecf20Sopenharmony_ci * fsl_mc_object_free - Returns an fsl-mc object to the resource
3208c2ecf20Sopenharmony_ci * pool where it came from.
3218c2ecf20Sopenharmony_ci * @mc_adev: Pointer to the fsl-mc device
3228c2ecf20Sopenharmony_ci */
3238c2ecf20Sopenharmony_civoid fsl_mc_object_free(struct fsl_mc_device *mc_adev)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct fsl_mc_resource *resource;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	resource = mc_adev->resource;
3288c2ecf20Sopenharmony_ci	if (resource->type == FSL_MC_POOL_DPMCP)
3298c2ecf20Sopenharmony_ci		return;
3308c2ecf20Sopenharmony_ci	if (resource->data != mc_adev)
3318c2ecf20Sopenharmony_ci		return;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	fsl_mc_resource_free(resource);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	mc_adev->consumer_link = NULL;
3368c2ecf20Sopenharmony_ci}
3378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_object_free);
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci/*
3408c2ecf20Sopenharmony_ci * A DPRC and the devices in the DPRC all share the same GIC-ITS device
3418c2ecf20Sopenharmony_ci * ID.  A block of IRQs is pre-allocated and maintained in a pool
3428c2ecf20Sopenharmony_ci * from which devices can allocate them when needed.
3438c2ecf20Sopenharmony_ci */
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci/*
3468c2ecf20Sopenharmony_ci * Initialize the interrupt pool associated with an fsl-mc bus.
3478c2ecf20Sopenharmony_ci * It allocates a block of IRQs from the GIC-ITS.
3488c2ecf20Sopenharmony_ci */
3498c2ecf20Sopenharmony_ciint fsl_mc_populate_irq_pool(struct fsl_mc_device *mc_bus_dev,
3508c2ecf20Sopenharmony_ci			     unsigned int irq_count)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	unsigned int i;
3538c2ecf20Sopenharmony_ci	struct msi_desc *msi_desc;
3548c2ecf20Sopenharmony_ci	struct fsl_mc_device_irq *irq_resources;
3558c2ecf20Sopenharmony_ci	struct fsl_mc_device_irq *mc_dev_irq;
3568c2ecf20Sopenharmony_ci	int error;
3578c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
3588c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool =
3598c2ecf20Sopenharmony_ci			&mc_bus->resource_pools[FSL_MC_POOL_IRQ];
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	/* do nothing if the IRQ pool is already populated */
3628c2ecf20Sopenharmony_ci	if (mc_bus->irq_resources)
3638c2ecf20Sopenharmony_ci		return 0;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	if (irq_count == 0 ||
3668c2ecf20Sopenharmony_ci	    irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)
3678c2ecf20Sopenharmony_ci		return -EINVAL;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
3708c2ecf20Sopenharmony_ci	if (error < 0)
3718c2ecf20Sopenharmony_ci		return error;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	irq_resources = devm_kcalloc(&mc_bus_dev->dev,
3748c2ecf20Sopenharmony_ci				     irq_count, sizeof(*irq_resources),
3758c2ecf20Sopenharmony_ci				     GFP_KERNEL);
3768c2ecf20Sopenharmony_ci	if (!irq_resources) {
3778c2ecf20Sopenharmony_ci		error = -ENOMEM;
3788c2ecf20Sopenharmony_ci		goto cleanup_msi_irqs;
3798c2ecf20Sopenharmony_ci	}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	for (i = 0; i < irq_count; i++) {
3828c2ecf20Sopenharmony_ci		mc_dev_irq = &irq_resources[i];
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci		/*
3858c2ecf20Sopenharmony_ci		 * NOTE: This mc_dev_irq's MSI addr/value pair will be set
3868c2ecf20Sopenharmony_ci		 * by the fsl_mc_msi_write_msg() callback
3878c2ecf20Sopenharmony_ci		 */
3888c2ecf20Sopenharmony_ci		mc_dev_irq->resource.type = res_pool->type;
3898c2ecf20Sopenharmony_ci		mc_dev_irq->resource.data = mc_dev_irq;
3908c2ecf20Sopenharmony_ci		mc_dev_irq->resource.parent_pool = res_pool;
3918c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&mc_dev_irq->resource.node);
3928c2ecf20Sopenharmony_ci		list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
3938c2ecf20Sopenharmony_ci	}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
3968c2ecf20Sopenharmony_ci		mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
3978c2ecf20Sopenharmony_ci		mc_dev_irq->msi_desc = msi_desc;
3988c2ecf20Sopenharmony_ci		mc_dev_irq->resource.id = msi_desc->irq;
3998c2ecf20Sopenharmony_ci	}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	res_pool->max_count = irq_count;
4028c2ecf20Sopenharmony_ci	res_pool->free_count = irq_count;
4038c2ecf20Sopenharmony_ci	mc_bus->irq_resources = irq_resources;
4048c2ecf20Sopenharmony_ci	return 0;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cicleanup_msi_irqs:
4078c2ecf20Sopenharmony_ci	fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4088c2ecf20Sopenharmony_ci	return error;
4098c2ecf20Sopenharmony_ci}
4108c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci/**
4138c2ecf20Sopenharmony_ci * Teardown the interrupt pool associated with an fsl-mc bus.
4148c2ecf20Sopenharmony_ci * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
4158c2ecf20Sopenharmony_ci */
4168c2ecf20Sopenharmony_civoid fsl_mc_cleanup_irq_pool(struct fsl_mc_device *mc_bus_dev)
4178c2ecf20Sopenharmony_ci{
4188c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
4198c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool =
4208c2ecf20Sopenharmony_ci			&mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	if (!mc_bus->irq_resources)
4238c2ecf20Sopenharmony_ci		return;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	if (res_pool->max_count == 0)
4268c2ecf20Sopenharmony_ci		return;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	if (res_pool->free_count != res_pool->max_count)
4298c2ecf20Sopenharmony_ci		return;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&res_pool->free_list);
4328c2ecf20Sopenharmony_ci	res_pool->max_count = 0;
4338c2ecf20Sopenharmony_ci	res_pool->free_count = 0;
4348c2ecf20Sopenharmony_ci	mc_bus->irq_resources = NULL;
4358c2ecf20Sopenharmony_ci	fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
4368c2ecf20Sopenharmony_ci}
4378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci/**
4408c2ecf20Sopenharmony_ci * Allocate the IRQs required by a given fsl-mc device.
4418c2ecf20Sopenharmony_ci */
4428c2ecf20Sopenharmony_ciint __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
4438c2ecf20Sopenharmony_ci{
4448c2ecf20Sopenharmony_ci	int i;
4458c2ecf20Sopenharmony_ci	int irq_count;
4468c2ecf20Sopenharmony_ci	int res_allocated_count = 0;
4478c2ecf20Sopenharmony_ci	int error = -EINVAL;
4488c2ecf20Sopenharmony_ci	struct fsl_mc_device_irq **irqs = NULL;
4498c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus;
4508c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	if (mc_dev->irqs)
4538c2ecf20Sopenharmony_ci		return -EINVAL;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	irq_count = mc_dev->obj_desc.irq_count;
4568c2ecf20Sopenharmony_ci	if (irq_count == 0)
4578c2ecf20Sopenharmony_ci		return -EINVAL;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	if (is_fsl_mc_bus_dprc(mc_dev))
4608c2ecf20Sopenharmony_ci		mc_bus = to_fsl_mc_bus(mc_dev);
4618c2ecf20Sopenharmony_ci	else
4628c2ecf20Sopenharmony_ci		mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (!mc_bus->irq_resources)
4658c2ecf20Sopenharmony_ci		return -EINVAL;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
4688c2ecf20Sopenharmony_ci	if (res_pool->free_count < irq_count) {
4698c2ecf20Sopenharmony_ci		dev_err(&mc_dev->dev,
4708c2ecf20Sopenharmony_ci			"Not able to allocate %u irqs for device\n", irq_count);
4718c2ecf20Sopenharmony_ci		return -ENOSPC;
4728c2ecf20Sopenharmony_ci	}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]),
4758c2ecf20Sopenharmony_ci			    GFP_KERNEL);
4768c2ecf20Sopenharmony_ci	if (!irqs)
4778c2ecf20Sopenharmony_ci		return -ENOMEM;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	for (i = 0; i < irq_count; i++) {
4808c2ecf20Sopenharmony_ci		struct fsl_mc_resource *resource;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci		error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
4838c2ecf20Sopenharmony_ci						 &resource);
4848c2ecf20Sopenharmony_ci		if (error < 0)
4858c2ecf20Sopenharmony_ci			goto error_resource_alloc;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci		irqs[i] = to_fsl_mc_irq(resource);
4888c2ecf20Sopenharmony_ci		res_allocated_count++;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci		irqs[i]->mc_dev = mc_dev;
4918c2ecf20Sopenharmony_ci		irqs[i]->dev_irq_index = i;
4928c2ecf20Sopenharmony_ci	}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	mc_dev->irqs = irqs;
4958c2ecf20Sopenharmony_ci	return 0;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_cierror_resource_alloc:
4988c2ecf20Sopenharmony_ci	for (i = 0; i < res_allocated_count; i++) {
4998c2ecf20Sopenharmony_ci		irqs[i]->mc_dev = NULL;
5008c2ecf20Sopenharmony_ci		fsl_mc_resource_free(&irqs[i]->resource);
5018c2ecf20Sopenharmony_ci	}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	return error;
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci/*
5088c2ecf20Sopenharmony_ci * Frees the IRQs that were allocated for an fsl-mc device.
5098c2ecf20Sopenharmony_ci */
5108c2ecf20Sopenharmony_civoid fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
5118c2ecf20Sopenharmony_ci{
5128c2ecf20Sopenharmony_ci	int i;
5138c2ecf20Sopenharmony_ci	int irq_count;
5148c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus;
5158c2ecf20Sopenharmony_ci	struct fsl_mc_device_irq **irqs = mc_dev->irqs;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	if (!irqs)
5188c2ecf20Sopenharmony_ci		return;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	irq_count = mc_dev->obj_desc.irq_count;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	if (is_fsl_mc_bus_dprc(mc_dev))
5238c2ecf20Sopenharmony_ci		mc_bus = to_fsl_mc_bus(mc_dev);
5248c2ecf20Sopenharmony_ci	else
5258c2ecf20Sopenharmony_ci		mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	if (!mc_bus->irq_resources)
5288c2ecf20Sopenharmony_ci		return;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	for (i = 0; i < irq_count; i++) {
5318c2ecf20Sopenharmony_ci		irqs[i]->mc_dev = NULL;
5328c2ecf20Sopenharmony_ci		fsl_mc_resource_free(&irqs[i]->resource);
5338c2ecf20Sopenharmony_ci	}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	mc_dev->irqs = NULL;
5368c2ecf20Sopenharmony_ci}
5378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_civoid fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	int pool_type;
5428c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
5458c2ecf20Sopenharmony_ci		struct fsl_mc_resource_pool *res_pool =
5468c2ecf20Sopenharmony_ci		    &mc_bus->resource_pools[pool_type];
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci		res_pool->type = pool_type;
5498c2ecf20Sopenharmony_ci		res_pool->max_count = 0;
5508c2ecf20Sopenharmony_ci		res_pool->free_count = 0;
5518c2ecf20Sopenharmony_ci		res_pool->mc_bus = mc_bus;
5528c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&res_pool->free_list);
5538c2ecf20Sopenharmony_ci		mutex_init(&res_pool->mutex);
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_cistatic void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
5588c2ecf20Sopenharmony_ci					 enum fsl_mc_pool_type pool_type)
5598c2ecf20Sopenharmony_ci{
5608c2ecf20Sopenharmony_ci	struct fsl_mc_resource *resource;
5618c2ecf20Sopenharmony_ci	struct fsl_mc_resource *next;
5628c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
5638c2ecf20Sopenharmony_ci	struct fsl_mc_resource_pool *res_pool =
5648c2ecf20Sopenharmony_ci					&mc_bus->resource_pools[pool_type];
5658c2ecf20Sopenharmony_ci	int free_count = 0;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
5688c2ecf20Sopenharmony_ci		free_count++;
5698c2ecf20Sopenharmony_ci		devm_kfree(&mc_bus_dev->dev, resource);
5708c2ecf20Sopenharmony_ci	}
5718c2ecf20Sopenharmony_ci}
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_civoid fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
5748c2ecf20Sopenharmony_ci{
5758c2ecf20Sopenharmony_ci	int pool_type;
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci	for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
5788c2ecf20Sopenharmony_ci		fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
5798c2ecf20Sopenharmony_ci}
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci/**
5828c2ecf20Sopenharmony_ci * fsl_mc_allocator_probe - callback invoked when an allocatable device is
5838c2ecf20Sopenharmony_ci * being added to the system
5848c2ecf20Sopenharmony_ci */
5858c2ecf20Sopenharmony_cistatic int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
5868c2ecf20Sopenharmony_ci{
5878c2ecf20Sopenharmony_ci	enum fsl_mc_pool_type pool_type;
5888c2ecf20Sopenharmony_ci	struct fsl_mc_device *mc_bus_dev;
5898c2ecf20Sopenharmony_ci	struct fsl_mc_bus *mc_bus;
5908c2ecf20Sopenharmony_ci	int error;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	if (!fsl_mc_is_allocatable(mc_dev))
5938c2ecf20Sopenharmony_ci		return -EINVAL;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
5968c2ecf20Sopenharmony_ci	if (!dev_is_fsl_mc(&mc_bus_dev->dev))
5978c2ecf20Sopenharmony_ci		return -EINVAL;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	mc_bus = to_fsl_mc_bus(mc_bus_dev);
6008c2ecf20Sopenharmony_ci	error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
6018c2ecf20Sopenharmony_ci	if (error < 0)
6028c2ecf20Sopenharmony_ci		return error;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
6058c2ecf20Sopenharmony_ci	if (error < 0)
6068c2ecf20Sopenharmony_ci		return error;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	dev_dbg(&mc_dev->dev,
6098c2ecf20Sopenharmony_ci		"Allocatable fsl-mc device bound to fsl_mc_allocator driver");
6108c2ecf20Sopenharmony_ci	return 0;
6118c2ecf20Sopenharmony_ci}
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci/**
6148c2ecf20Sopenharmony_ci * fsl_mc_allocator_remove - callback invoked when an allocatable device is
6158c2ecf20Sopenharmony_ci * being removed from the system
6168c2ecf20Sopenharmony_ci */
6178c2ecf20Sopenharmony_cistatic int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
6188c2ecf20Sopenharmony_ci{
6198c2ecf20Sopenharmony_ci	int error;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (!fsl_mc_is_allocatable(mc_dev))
6228c2ecf20Sopenharmony_ci		return -EINVAL;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	if (mc_dev->resource) {
6258c2ecf20Sopenharmony_ci		error = fsl_mc_resource_pool_remove_device(mc_dev);
6268c2ecf20Sopenharmony_ci		if (error < 0)
6278c2ecf20Sopenharmony_ci			return error;
6288c2ecf20Sopenharmony_ci	}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	dev_dbg(&mc_dev->dev,
6318c2ecf20Sopenharmony_ci		"Allocatable fsl-mc device unbound from fsl_mc_allocator driver");
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_cistatic const struct fsl_mc_device_id match_id_table[] = {
6368c2ecf20Sopenharmony_ci	{
6378c2ecf20Sopenharmony_ci	 .vendor = FSL_MC_VENDOR_FREESCALE,
6388c2ecf20Sopenharmony_ci	 .obj_type = "dpbp",
6398c2ecf20Sopenharmony_ci	},
6408c2ecf20Sopenharmony_ci	{
6418c2ecf20Sopenharmony_ci	 .vendor = FSL_MC_VENDOR_FREESCALE,
6428c2ecf20Sopenharmony_ci	 .obj_type = "dpmcp",
6438c2ecf20Sopenharmony_ci	},
6448c2ecf20Sopenharmony_ci	{
6458c2ecf20Sopenharmony_ci	 .vendor = FSL_MC_VENDOR_FREESCALE,
6468c2ecf20Sopenharmony_ci	 .obj_type = "dpcon",
6478c2ecf20Sopenharmony_ci	},
6488c2ecf20Sopenharmony_ci	{.vendor = 0x0},
6498c2ecf20Sopenharmony_ci};
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_cistatic struct fsl_mc_driver fsl_mc_allocator_driver = {
6528c2ecf20Sopenharmony_ci	.driver = {
6538c2ecf20Sopenharmony_ci		   .name = "fsl_mc_allocator",
6548c2ecf20Sopenharmony_ci		   .pm = NULL,
6558c2ecf20Sopenharmony_ci		   },
6568c2ecf20Sopenharmony_ci	.match_id_table = match_id_table,
6578c2ecf20Sopenharmony_ci	.probe = fsl_mc_allocator_probe,
6588c2ecf20Sopenharmony_ci	.remove = fsl_mc_allocator_remove,
6598c2ecf20Sopenharmony_ci};
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ciint __init fsl_mc_allocator_driver_init(void)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	return fsl_mc_driver_register(&fsl_mc_allocator_driver);
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_civoid fsl_mc_allocator_driver_exit(void)
6678c2ecf20Sopenharmony_ci{
6688c2ecf20Sopenharmony_ci	fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
6698c2ecf20Sopenharmony_ci}
670