1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 Linaro Limited, All rights reserved.
4 * Author: Mike Leach <mike.leach@linaro.org>
7 #include <linux/platform_device.h>
9 #include "coresight-config.h"
10 #include "coresight-syscfg.h"
13 * cscfg_ API manages configurations and features for the entire coresight
16 * It allows the loading of configurations and features, and loads these into
17 * coresight devices as appropriate.
20 /* protect the cscsg_data and device */
21 static DEFINE_MUTEX(cscfg_mutex);
23 /* only one of these */
24 static struct cscfg_manager *cscfg_mgr;
26 /* load features and configuations into the lists */
28 /* check feature list for a named feature - call with mutex locked. */
29 static bool cscfg_match_list_feat(const char *name)
31 struct cscfg_feature_desc *feat_desc;
33 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
34 if (strcmp(feat_desc->name, name) == 0)
40 /* check all feat needed for cfg are in the list - call with mutex locked. */
41 static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *config_desc)
45 for (i = 0; i < config_desc->nr_feat_refs; i++)
46 if (!cscfg_match_list_feat(config_desc->feat_ref_names[i]))
52 * load feature - add to feature list.
54 static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc)
56 list_add(&feat_desc->item, &cscfg_mgr->feat_desc_list);
62 * load config into the system - validate used features exist then add to
65 static int cscfg_load_config(struct cscfg_config_desc *config_desc)
69 /* validate features are present */
70 err = cscfg_check_feat_for_cfg(config_desc);
74 list_add(&config_desc->item, &cscfg_mgr->config_desc_list);
79 * cscfg_load_config_sets - API function to load feature and config sets.
81 * Take a 0 terminated array of feature descriptors and/or configuration
82 * descriptors and load into the system.
83 * Features are loaded first to ensure configuration dependencies can be met.
85 * @config_descs: 0 terminated array of configuration descriptors.
86 * @feat_descs: 0 terminated array of feature descriptors.
88 int cscfg_load_config_sets(struct cscfg_config_desc **config_descs,
89 struct cscfg_feature_desc **feat_descs)
93 mutex_lock(&cscfg_mutex);
95 /* load features first */
97 while (feat_descs[i]) {
98 err = cscfg_load_feat(feat_descs[i]);
100 pr_err("coresight-syscfg: Failed to load feature %s\n",
101 feat_descs[i]->name);
108 /* next any configurations to check feature dependencies */
111 while (config_descs[i]) {
112 err = cscfg_load_config(config_descs[i]);
114 pr_err("coresight-syscfg: Failed to load configuration %s\n",
115 config_descs[i]->name);
123 mutex_unlock(&cscfg_mutex);
126 EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
128 /* Initialise system configuration management device. */
130 struct device *cscfg_device(void)
132 return cscfg_mgr ? &cscfg_mgr->dev : NULL;
135 /* Must have a release function or the kernel will complain on module unload */
136 static void cscfg_dev_release(struct device *dev)
142 /* a device is needed to "own" some kernel elements such as sysfs entries. */
143 static int cscfg_create_device(void)
148 mutex_lock(&cscfg_mutex);
151 goto create_dev_exit_unlock;
154 cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
156 goto create_dev_exit_unlock;
158 /* setup the device */
159 dev = cscfg_device();
160 dev->release = cscfg_dev_release;
161 dev->init_name = "cs_system_cfg";
163 err = device_register(dev);
165 cscfg_dev_release(dev);
167 create_dev_exit_unlock:
168 mutex_unlock(&cscfg_mutex);
172 static void cscfg_clear_device(void)
174 mutex_lock(&cscfg_mutex);
175 device_unregister(cscfg_device());
176 mutex_unlock(&cscfg_mutex);
179 /* Initialise system config management API device */
180 int __init cscfg_init(void)
184 err = cscfg_create_device();
188 INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list);
189 INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list);
190 INIT_LIST_HEAD(&cscfg_mgr->config_desc_list);
192 dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
196 void cscfg_exit(void)
198 cscfg_clear_device();