0001
0002
0003
0004
0005
0006
0007 #include <linux/sysfs.h>
0008 #include "coresight-config.h"
0009 #include "coresight-priv.h"
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 static void cscfg_set_reg(struct cscfg_regval_csdev *reg_csdev)
0022 {
0023 u32 *p_val32 = (u32 *)reg_csdev->driver_regval;
0024 u32 tmp32 = reg_csdev->reg_desc.val32;
0025
0026 if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT) {
0027 *((u64 *)reg_csdev->driver_regval) = reg_csdev->reg_desc.val64;
0028 return;
0029 }
0030
0031 if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_MASK) {
0032 tmp32 = *p_val32;
0033 tmp32 &= ~reg_csdev->reg_desc.mask32;
0034 tmp32 |= reg_csdev->reg_desc.val32 & reg_csdev->reg_desc.mask32;
0035 }
0036 *p_val32 = tmp32;
0037 }
0038
0039
0040
0041
0042 static void cscfg_save_reg(struct cscfg_regval_csdev *reg_csdev)
0043 {
0044 if (!(reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_SAVE))
0045 return;
0046 if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT)
0047 reg_csdev->reg_desc.val64 = *(u64 *)(reg_csdev->driver_regval);
0048 else
0049 reg_csdev->reg_desc.val32 = *(u32 *)(reg_csdev->driver_regval);
0050 }
0051
0052
0053
0054
0055
0056 static void cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev,
0057 struct cscfg_regval_desc *reg_desc,
0058 struct cscfg_regval_csdev *reg_csdev)
0059 {
0060 struct cscfg_parameter_csdev *param_csdev;
0061
0062
0063 param_csdev = &feat_csdev->params_csdev[reg_desc->param_idx];
0064 param_csdev->reg_csdev = reg_csdev;
0065 param_csdev->val64 = reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT;
0066
0067 if (param_csdev->val64)
0068 reg_csdev->reg_desc.val64 = param_csdev->current_value;
0069 else
0070 reg_csdev->reg_desc.val32 = (u32)param_csdev->current_value;
0071 }
0072
0073
0074 static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
0075 {
0076 unsigned long flags;
0077 int i;
0078
0079 spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
0080 for (i = 0; i < feat_csdev->nr_regs; i++)
0081 cscfg_set_reg(&feat_csdev->regs_csdev[i]);
0082 spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
0083 dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
0084 feat_csdev->feat_desc->name, "set on enable");
0085 return 0;
0086 }
0087
0088
0089 static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
0090 {
0091 unsigned long flags;
0092 int i;
0093
0094 spin_lock_irqsave(feat_csdev->drv_spinlock, flags);
0095 for (i = 0; i < feat_csdev->nr_regs; i++)
0096 cscfg_save_reg(&feat_csdev->regs_csdev[i]);
0097 spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
0098 dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
0099 feat_csdev->feat_desc->name, "save on disable");
0100 }
0101
0102
0103 void cscfg_reset_feat(struct cscfg_feature_csdev *feat_csdev)
0104 {
0105 struct cscfg_regval_desc *reg_desc;
0106 struct cscfg_regval_csdev *reg_csdev;
0107 int i;
0108
0109
0110
0111
0112
0113 for (i = 0; i < feat_csdev->nr_params; i++)
0114 feat_csdev->params_csdev[i].current_value =
0115 feat_csdev->feat_desc->params_desc[i].value;
0116
0117 for (i = 0; i < feat_csdev->nr_regs; i++) {
0118 reg_desc = &feat_csdev->feat_desc->regs_desc[i];
0119 reg_csdev = &feat_csdev->regs_csdev[i];
0120 reg_csdev->reg_desc.type = reg_desc->type;
0121
0122
0123 if (reg_desc->type & CS_CFG_REG_TYPE_VAL_PARAM)
0124 cscfg_init_reg_param(feat_csdev, reg_desc, reg_csdev);
0125 else
0126
0127
0128
0129
0130 reg_csdev->reg_desc.val64 = reg_desc->val64;
0131 }
0132 }
0133
0134
0135
0136
0137
0138 static int cscfg_update_presets(struct cscfg_config_csdev *config_csdev, int preset)
0139 {
0140 int i, j, val_idx = 0, nr_cfg_params;
0141 struct cscfg_parameter_csdev *param_csdev;
0142 struct cscfg_feature_csdev *feat_csdev;
0143 const struct cscfg_config_desc *config_desc = config_csdev->config_desc;
0144 const char *name;
0145 const u64 *preset_base;
0146 u64 val;
0147
0148
0149 if (preset < 1 || preset > config_desc->nr_presets)
0150 return -EINVAL;
0151
0152
0153
0154
0155
0156
0157
0158 nr_cfg_params = config_desc->nr_total_params;
0159 preset_base = &config_desc->presets[(preset - 1) * nr_cfg_params];
0160 for (i = 0; i < config_csdev->nr_feat; i++) {
0161 feat_csdev = config_csdev->feats_csdev[i];
0162 if (!feat_csdev->nr_params)
0163 continue;
0164
0165 for (j = 0; j < feat_csdev->nr_params; j++) {
0166 param_csdev = &feat_csdev->params_csdev[j];
0167 name = feat_csdev->feat_desc->params_desc[j].name;
0168 val = preset_base[val_idx++];
0169 if (param_csdev->val64) {
0170 dev_dbg(&config_csdev->csdev->dev,
0171 "set param %s (%lld)", name, val);
0172 param_csdev->reg_csdev->reg_desc.val64 = val;
0173 } else {
0174 param_csdev->reg_csdev->reg_desc.val32 = (u32)val;
0175 dev_dbg(&config_csdev->csdev->dev,
0176 "set param %s (%d)", name, (u32)val);
0177 }
0178 }
0179
0180
0181 if (val_idx >= nr_cfg_params)
0182 break;
0183 }
0184 return 0;
0185 }
0186
0187
0188
0189
0190
0191
0192 static int cscfg_update_curr_params(struct cscfg_config_csdev *config_csdev)
0193 {
0194 int i, j;
0195 struct cscfg_feature_csdev *feat_csdev;
0196 struct cscfg_parameter_csdev *param_csdev;
0197 const char *name;
0198 u64 val;
0199
0200 for (i = 0; i < config_csdev->nr_feat; i++) {
0201 feat_csdev = config_csdev->feats_csdev[i];
0202 if (!feat_csdev->nr_params)
0203 continue;
0204 for (j = 0; j < feat_csdev->nr_params; j++) {
0205 param_csdev = &feat_csdev->params_csdev[j];
0206 name = feat_csdev->feat_desc->params_desc[j].name;
0207 val = param_csdev->current_value;
0208 if (param_csdev->val64) {
0209 dev_dbg(&config_csdev->csdev->dev,
0210 "set param %s (%lld)", name, val);
0211 param_csdev->reg_csdev->reg_desc.val64 = val;
0212 } else {
0213 param_csdev->reg_csdev->reg_desc.val32 = (u32)val;
0214 dev_dbg(&config_csdev->csdev->dev,
0215 "set param %s (%d)", name, (u32)val);
0216 }
0217 }
0218 }
0219 return 0;
0220 }
0221
0222
0223
0224
0225
0226 static int cscfg_prog_config(struct cscfg_config_csdev *config_csdev, bool enable)
0227 {
0228 int i, err = 0;
0229 struct cscfg_feature_csdev *feat_csdev;
0230 struct coresight_device *csdev;
0231
0232 for (i = 0; i < config_csdev->nr_feat; i++) {
0233 feat_csdev = config_csdev->feats_csdev[i];
0234 csdev = feat_csdev->csdev;
0235 dev_dbg(&csdev->dev, "cfg %s; %s feature:%s", config_csdev->config_desc->name,
0236 enable ? "enable" : "disable", feat_csdev->feat_desc->name);
0237
0238 if (enable)
0239 err = cscfg_set_on_enable(feat_csdev);
0240 else
0241 cscfg_save_on_disable(feat_csdev);
0242
0243 if (err)
0244 break;
0245 }
0246 return err;
0247 }
0248
0249
0250
0251
0252
0253
0254
0255
0256 int cscfg_csdev_enable_config(struct cscfg_config_csdev *config_csdev, int preset)
0257 {
0258 int err = 0;
0259
0260 if (preset)
0261 err = cscfg_update_presets(config_csdev, preset);
0262 else
0263 err = cscfg_update_curr_params(config_csdev);
0264 if (!err)
0265 err = cscfg_prog_config(config_csdev, true);
0266 return err;
0267 }
0268
0269 void cscfg_csdev_disable_config(struct cscfg_config_csdev *config_csdev)
0270 {
0271 cscfg_prog_config(config_csdev, false);
0272 }