/* * This provides a set of generic functions that operate on configurations * and features to manage the handling of parameters, the programming and * saving of registers used by features on devices.
*/
/* * Write the value held in the register structure into the driver internal memory * location.
*/ staticvoid cscfg_set_reg(struct cscfg_regval_csdev *reg_csdev)
{
u32 *p_val32 = (u32 *)reg_csdev->driver_regval;
u32 tmp32 = reg_csdev->reg_desc.val32;
/* * Read the driver value into the reg if this is marked as one we want to save.
*/ staticvoid cscfg_save_reg(struct cscfg_regval_csdev *reg_csdev)
{ if (!(reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_SAVE)) return; if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT)
reg_csdev->reg_desc.val64 = *(u64 *)(reg_csdev->driver_regval); else
reg_csdev->reg_desc.val32 = *(u32 *)(reg_csdev->driver_regval);
}
/* * Some register values are set from parameters. Initialise these registers * from the current parameter values.
*/ staticvoid cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev, struct cscfg_regval_desc *reg_desc, struct cscfg_regval_csdev *reg_csdev)
{ struct cscfg_parameter_csdev *param_csdev;
/* for param, load routines have validated the index */
param_csdev = &feat_csdev->params_csdev[reg_desc->param_idx];
param_csdev->reg_csdev = reg_csdev;
param_csdev->val64 = reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT;
if (param_csdev->val64)
reg_csdev->reg_desc.val64 = param_csdev->current_value; else
reg_csdev->reg_desc.val32 = (u32)param_csdev->current_value;
}
/* set values into the driver locations referenced in cscfg_reg_csdev */ staticint cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
{ unsignedlong flags; int i;
raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags); for (i = 0; i < feat_csdev->nr_regs; i++)
cscfg_set_reg(&feat_csdev->regs_csdev[i]);
raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
feat_csdev->feat_desc->name, "set on enable"); return 0;
}
/* copy back values from the driver locations referenced in cscfg_reg_csdev */ staticvoid cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
{ unsignedlong flags; int i;
raw_spin_lock_irqsave(feat_csdev->drv_spinlock, flags); for (i = 0; i < feat_csdev->nr_regs; i++)
cscfg_save_reg(&feat_csdev->regs_csdev[i]);
raw_spin_unlock_irqrestore(feat_csdev->drv_spinlock, flags);
dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
feat_csdev->feat_desc->name, "save on disable");
}
/* * set the default values for all parameters and regs from the * relevant static descriptors.
*/ for (i = 0; i < feat_csdev->nr_params; i++)
feat_csdev->params_csdev[i].current_value =
feat_csdev->feat_desc->params_desc[i].value;
for (i = 0; i < feat_csdev->nr_regs; i++) {
reg_desc = &feat_csdev->feat_desc->regs_desc[i];
reg_csdev = &feat_csdev->regs_csdev[i];
reg_csdev->reg_desc.type = reg_desc->type;
/* check if reg set from a parameter otherwise desc default */ if (reg_desc->type & CS_CFG_REG_TYPE_VAL_PARAM)
cscfg_init_reg_param(feat_csdev, reg_desc, reg_csdev); else /* * for normal values the union between val64 & val32 + mask32 * allows us to init using the 64 bit value
*/
reg_csdev->reg_desc.val64 = reg_desc->val64;
}
}
/* * For the selected presets, we set the register associated with the parameter, to * the value of the preset index associated with the parameter.
*/ staticint cscfg_update_presets(struct cscfg_config_csdev *config_csdev, int preset)
{ int i, j, val_idx = 0, nr_cfg_params; struct cscfg_parameter_csdev *param_csdev; struct cscfg_feature_csdev *feat_csdev; conststruct cscfg_config_desc *config_desc = config_csdev->config_desc; constchar *name; const u64 *preset_base;
u64 val;
/* preset in range 1 to nr_presets */ if (preset < 1 || preset > config_desc->nr_presets) return -EINVAL; /* * Go through the array of features, assigning preset values to * feature parameters in the order they appear. * There should be precisely the same number of preset values as the * sum of number of parameters over all the features - but we will * ensure there is no overrun.
*/
nr_cfg_params = config_desc->nr_total_params;
preset_base = &config_desc->presets[(preset - 1) * nr_cfg_params]; for (i = 0; i < config_csdev->nr_feat; i++) {
feat_csdev = config_csdev->feats_csdev[i]; if (!feat_csdev->nr_params) continue;
/* exit early if all params filled */ if (val_idx >= nr_cfg_params) break;
} return 0;
}
/* * if we are not using a preset, then need to update the feature params * with current values. This sets the register associated with the parameter * with the current value of that parameter.
*/ staticint cscfg_update_curr_params(struct cscfg_config_csdev *config_csdev)
{ int i, j; struct cscfg_feature_csdev *feat_csdev; struct cscfg_parameter_csdev *param_csdev; constchar *name;
u64 val;
for (i = 0; i < config_csdev->nr_feat; i++) {
feat_csdev = config_csdev->feats_csdev[i]; if (!feat_csdev->nr_params) continue; for (j = 0; j < feat_csdev->nr_params; j++) {
param_csdev = &feat_csdev->params_csdev[j];
name = feat_csdev->feat_desc->params_desc[j].name;
val = param_csdev->current_value; if (param_csdev->val64) {
dev_dbg(&config_csdev->csdev->dev, "set param %s (%lld)", name, val);
param_csdev->reg_csdev->reg_desc.val64 = val;
} else {
param_csdev->reg_csdev->reg_desc.val32 = (u32)val;
dev_dbg(&config_csdev->csdev->dev, "set param %s (%d)", name, (u32)val);
}
}
} return 0;
}
/* * Configuration values will be programmed into the driver locations if enabling, or read * from relevant locations on disable.
*/ staticint cscfg_prog_config(struct cscfg_config_csdev *config_csdev, bool enable)
{ int i, err = 0; struct cscfg_feature_csdev *feat_csdev; struct coresight_device *csdev;
for (i = 0; i < config_csdev->nr_feat; i++) {
feat_csdev = config_csdev->feats_csdev[i];
csdev = feat_csdev->csdev;
dev_dbg(&csdev->dev, "cfg %s; %s feature:%s", config_csdev->config_desc->name,
enable ? "enable" : "disable", feat_csdev->feat_desc->name);
if (enable)
err = cscfg_set_on_enable(feat_csdev); else
cscfg_save_on_disable(feat_csdev);
if (err) break;
} return err;
}
/* * Enable configuration for the device. Will result in the internal driver data * being updated ready for programming into the device. * * @config_csdev: config_csdev to set. * @preset: preset values to use - 0 for default.
*/ int cscfg_csdev_enable_config(struct cscfg_config_csdev *config_csdev, int preset)
{ int err = 0;
if (preset)
err = cscfg_update_presets(config_csdev, preset); else
err = cscfg_update_curr_params(config_csdev); if (!err)
err = cscfg_prog_config(config_csdev, true); return err;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.