Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / hwtracing / coresight / coresight-config.c
blob4723bf7402a2777376368b540f07c39bba72476f
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright(C) 2020 Linaro Limited. All rights reserved.
4 * Author: Mike Leach <mike.leach@linaro.org>
5 */
7 #include <linux/sysfs.h>
8 #include "coresight-config.h"
9 #include "coresight-priv.h"
12 * This provides a set of generic functions that operate on configurations
13 * and features to manage the handling of parameters, the programming and
14 * saving of registers used by features on devices.
18 * Write the value held in the register structure into the driver internal memory
19 * location.
21 static void cscfg_set_reg(struct cscfg_regval_csdev *reg_csdev)
23 u32 *p_val32 = (u32 *)reg_csdev->driver_regval;
24 u32 tmp32 = reg_csdev->reg_desc.val32;
26 if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT) {
27 *((u64 *)reg_csdev->driver_regval) = reg_csdev->reg_desc.val64;
28 return;
31 if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_MASK) {
32 tmp32 = *p_val32;
33 tmp32 &= ~reg_csdev->reg_desc.mask32;
34 tmp32 |= reg_csdev->reg_desc.val32 & reg_csdev->reg_desc.mask32;
36 *p_val32 = tmp32;
40 * Read the driver value into the reg if this is marked as one we want to save.
42 static void cscfg_save_reg(struct cscfg_regval_csdev *reg_csdev)
44 if (!(reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_SAVE))
45 return;
46 if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT)
47 reg_csdev->reg_desc.val64 = *(u64 *)(reg_csdev->driver_regval);
48 else
49 reg_csdev->reg_desc.val32 = *(u32 *)(reg_csdev->driver_regval);
53 * Some register values are set from parameters. Initialise these registers
54 * from the current parameter values.
56 static void cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev,
57 struct cscfg_regval_desc *reg_desc,
58 struct cscfg_regval_csdev *reg_csdev)
60 struct cscfg_parameter_csdev *param_csdev;
62 /* for param, load routines have validated the index */
63 param_csdev = &feat_csdev->params_csdev[reg_desc->param_idx];
64 param_csdev->reg_csdev = reg_csdev;
65 param_csdev->val64 = reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT;
67 if (param_csdev->val64)
68 reg_csdev->reg_desc.val64 = param_csdev->current_value;
69 else
70 reg_csdev->reg_desc.val32 = (u32)param_csdev->current_value;
73 /* set values into the driver locations referenced in cscfg_reg_csdev */
74 static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
76 unsigned long flags;
77 int i;
79 spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
80 for (i = 0; i < feat_csdev->nr_regs; i++)
81 cscfg_set_reg(&feat_csdev->regs_csdev[i]);
82 spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
83 dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
84 feat_csdev->feat_desc->name, "set on enable");
85 return 0;
88 /* copy back values from the driver locations referenced in cscfg_reg_csdev */
89 static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
91 unsigned long flags;
92 int i;
94 spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
95 for (i = 0; i < feat_csdev->nr_regs; i++)
96 cscfg_save_reg(&feat_csdev->regs_csdev[i]);
97 spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
98 dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
99 feat_csdev->feat_desc->name, "save on disable");
102 /* default reset - restore default values */
103 void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev)
105 struct cscfg_regval_desc *reg_desc;
106 struct cscfg_regval_csdev *reg_csdev;
107 int i;
110 * set the default values for all parameters and regs from the
111 * relevant static descriptors.
113 for (i = 0; i < feat_csdev->nr_params; i++)
114 feat_csdev->params_csdev[i].current_value =
115 feat_csdev->feat_desc->params_desc[i].value;
117 for (i = 0; i < feat_csdev->nr_regs; i++) {
118 reg_desc = &feat_csdev->feat_desc->regs_desc[i];
119 reg_csdev = &feat_csdev->regs_csdev[i];
120 reg_csdev->reg_desc.type = reg_desc->type;
122 /* check if reg set from a parameter otherwise desc default */
123 if (reg_desc->type & CS_CFG_REG_TYPE_VAL_PARAM)
124 cscfg_init_reg_param(feat_csdev, reg_desc, reg_csdev);
125 else
127 * for normal values the union between val64 & val32 + mask32
128 * allows us to init using the 64 bit value
130 reg_csdev->reg_desc.val64 = reg_desc->val64;
135 * For the selected presets, we set the register associated with the parameter, to
136 * the value of the preset index associated with the parameter.
138 static int cscfg_update_presets(struct cscfg_config_csdev *config_csdev, int preset)
140 int i, j, val_idx = 0, nr_cfg_params;
141 struct cscfg_parameter_csdev *param_csdev;
142 struct cscfg_feature_csdev *feat_csdev;
143 const struct cscfg_config_desc *config_desc = config_csdev->config_desc;
144 const char *name;
145 const u64 *preset_base;
146 u64 val;
148 /* preset in range 1 to nr_presets */
149 if (preset < 1 || preset > config_desc->nr_presets)
150 return -EINVAL;
152 * Go through the array of features, assigning preset values to
153 * feature parameters in the order they appear.
154 * There should be precisely the same number of preset values as the
155 * sum of number of parameters over all the features - but we will
156 * ensure there is no overrun.
158 nr_cfg_params = config_desc->nr_total_params;
159 preset_base = &config_desc->presets[(preset - 1) * nr_cfg_params];
160 for (i = 0; i < config_csdev->nr_feat; i++) {
161 feat_csdev = config_csdev->feats_csdev[i];
162 if (!feat_csdev->nr_params)
163 continue;
165 for (j = 0; j < feat_csdev->nr_params; j++) {
166 param_csdev = &feat_csdev->params_csdev[j];
167 name = feat_csdev->feat_desc->params_desc[j].name;
168 val = preset_base[val_idx++];
169 if (param_csdev->val64) {
170 dev_dbg(&config_csdev->csdev->dev,
171 "set param %s (%lld)", name, val);
172 param_csdev->reg_csdev->reg_desc.val64 = val;
173 } else {
174 param_csdev->reg_csdev->reg_desc.val32 = (u32)val;
175 dev_dbg(&config_csdev->csdev->dev,
176 "set param %s (%d)", name, (u32)val);
180 /* exit early if all params filled */
181 if (val_idx >= nr_cfg_params)
182 break;
184 return 0;
188 * if we are not using a preset, then need to update the feature params
189 * with current values. This sets the register associated with the parameter
190 * with the current value of that parameter.
192 static int cscfg_update_curr_params(struct cscfg_config_csdev *config_csdev)
194 int i, j;
195 struct cscfg_feature_csdev *feat_csdev;
196 struct cscfg_parameter_csdev *param_csdev;
197 const char *name;
198 u64 val;
200 for (i = 0; i < config_csdev->nr_feat; i++) {
201 feat_csdev = config_csdev->feats_csdev[i];
202 if (!feat_csdev->nr_params)
203 continue;
204 for (j = 0; j < feat_csdev->nr_params; j++) {
205 param_csdev = &feat_csdev->params_csdev[j];
206 name = feat_csdev->feat_desc->params_desc[j].name;
207 val = param_csdev->current_value;
208 if (param_csdev->val64) {
209 dev_dbg(&config_csdev->csdev->dev,
210 "set param %s (%lld)", name, val);
211 param_csdev->reg_csdev->reg_desc.val64 = val;
212 } else {
213 param_csdev->reg_csdev->reg_desc.val32 = (u32)val;
214 dev_dbg(&config_csdev->csdev->dev,
215 "set param %s (%d)", name, (u32)val);
219 return 0;
223 * Configuration values will be programmed into the driver locations if enabling, or read
224 * from relevant locations on disable.
226 static int cscfg_prog_config(struct cscfg_config_csdev *config_csdev, bool enable)
228 int i, err = 0;
229 struct cscfg_feature_csdev *feat_csdev;
230 struct coresight_device *csdev;
232 for (i = 0; i < config_csdev->nr_feat; i++) {
233 feat_csdev = config_csdev->feats_csdev[i];
234 csdev = feat_csdev->csdev;
235 dev_dbg(&csdev->dev, "cfg %s; %s feature:%s", config_csdev->config_desc->name,
236 enable ? "enable" : "disable", feat_csdev->feat_desc->name);
238 if (enable)
239 err = cscfg_set_on_enable(feat_csdev);
240 else
241 cscfg_save_on_disable(feat_csdev);
243 if (err)
244 break;
246 return err;
250 * Enable configuration for the device. Will result in the internal driver data
251 * being updated ready for programming into the device.
253 * @config_csdev: config_csdev to set.
254 * @preset: preset values to use - 0 for default.
256 int cscfg_csdev_enable_config(struct cscfg_config_csdev *config_csdev, int preset)
258 int err = 0;
260 if (preset)
261 err = cscfg_update_presets(config_csdev, preset);
262 else
263 err = cscfg_update_curr_params(config_csdev);
264 if (!err)
265 err = cscfg_prog_config(config_csdev, true);
266 return err;
269 void cscfg_csdev_disable_config(struct cscfg_config_csdev *config_csdev)
271 cscfg_prog_config(config_csdev, false);