enum {
AM62A7_EFUSE_M_MPU_OPP = 13,
AM62A7_EFUSE_N_MPU_OPP,
AM62A7_EFUSE_O_MPU_OPP,
AM62A7_EFUSE_P_MPU_OPP,
AM62A7_EFUSE_Q_MPU_OPP,
AM62A7_EFUSE_R_MPU_OPP,
AM62A7_EFUSE_S_MPU_OPP, /* * The V, U, and T speed grade numbering is out of order * to align with the AM625 more uniformly. I promise I know * my ABCs ;)
*/
AM62A7_EFUSE_V_MPU_OPP,
AM62A7_EFUSE_U_MPU_OPP,
AM62A7_EFUSE_T_MPU_OPP,
};
/* * The efuse on dra7 and am57 parts contains a specific * value indicating the highest available OPP.
*/
switch (efuse) { case DRA76_EFUSE_HAS_PLUS_MPU_OPP: case DRA76_EFUSE_HAS_ALL_MPU_OPP:
calculated_efuse |= DRA76_EFUSE_PLUS_MPU_OPP;
fallthrough; case DRA7_EFUSE_HAS_ALL_MPU_OPP: case DRA7_EFUSE_HAS_HIGH_MPU_OPP:
calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP;
fallthrough; case DRA7_EFUSE_HAS_OD_MPU_OPP:
calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP;
}
return calculated_efuse;
}
staticunsignedlong omap3_efuse_xlate(struct ti_cpufreq_data *opp_data, unsignedlong efuse)
{ /* OPP enable bit ("Speed Binned") */ return BIT(efuse);
}
switch (efuse) { case AM62A7_EFUSE_V_MPU_OPP: case AM62A7_EFUSE_U_MPU_OPP: case AM62A7_EFUSE_T_MPU_OPP: case AM62A7_EFUSE_S_MPU_OPP:
calculated_efuse |= AM62A7_SUPPORT_V_MPU_OPP;
fallthrough; case AM62A7_EFUSE_R_MPU_OPP: case AM62A7_EFUSE_Q_MPU_OPP: case AM62A7_EFUSE_P_MPU_OPP: case AM62A7_EFUSE_O_MPU_OPP:
calculated_efuse |= AM62A7_SUPPORT_R_MPU_OPP;
fallthrough; case AM62A7_EFUSE_N_MPU_OPP: case AM62A7_EFUSE_M_MPU_OPP:
calculated_efuse |= AM62A7_SUPPORT_N_MPU_OPP;
}
/* * OMAP35x TRM (SPRUF98K): * CONTROL_IDCODE (0x4830 A204) describes Silicon revisions. * Control OMAP Status Register 15:0 (Address 0x4800 244C) * to separate between omap3503, omap3515, omap3525, omap3530 * and feature presence. * There are encodings for versions limited to 400/266MHz * but we ignore. * Not clear if this also holds for omap34xx. * some eFuse values e.g. CONTROL_FUSE_OPP1_VDD1 * are stored in the SYSCON register range * Register 0x4830A20C [ProdID.SKUID] [0:3] * 0x0 for normal 600/430MHz device. * 0x8 for 720/520MHz device. * Not clear what omap34xx value is.
*/
/* * AM/DM37x TRM (SPRUGN4M) * CONTROL_IDCODE (0x4830 A204) describes Silicon revisions. * Control Device Status Register 15:0 (Address 0x4800 244C) * to separate between am3703, am3715, dm3725, dm3730 * and feature presence. * Speed Binned = Bit 9 * 0 800/600 MHz * 1 1000/800 MHz * some eFuse values e.g. CONTROL_FUSE_OPP 1G_VDD1 * are stored in the SYSCON register range. * There is no 0x4830A20C [ProdID.SKUID] register (exists but * seems to always read as 0).
*/
/** * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC * @opp_data: pointer to ti_cpufreq_data context * @efuse_value: Set to the value parsed from efuse * * Returns error code if efuse not read properly.
*/ staticint ti_cpufreq_get_efuse(struct ti_cpufreq_data *opp_data,
u32 *efuse_value)
{ struct device *dev = opp_data->cpu_dev;
u32 efuse; int ret;
ret = regmap_read(opp_data->syscon, opp_data->soc_data->efuse_offset,
&efuse);
if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_IS_SINGLE_REG && ret == -EIO)
ret = regmap_read(opp_data->syscon, 0x0, &efuse);
if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { /* not a syscon register! */ void __iomem *regs = ioremap(OMAP3_SYSCON_BASE +
opp_data->soc_data->efuse_offset, 4);
if (!regs) return -ENOMEM;
efuse = readl(regs);
iounmap(regs);
} elseif (ret) {
dev_err(dev, "Failed to read the efuse value from syscon: %d\n",
ret); return ret;
}
/** * ti_cpufreq_get_rev() - Parse and return rev value present on SoC * @opp_data: pointer to ti_cpufreq_data context * @revision_value: Set to the value parsed from revision register * * Returns error code if revision not read properly.
*/ staticint ti_cpufreq_get_rev(struct ti_cpufreq_data *opp_data,
u32 *revision_value)
{ struct device *dev = opp_data->cpu_dev;
u32 revision; int ret; if (soc_device_match(k3_cpufreq_soc)) { /* * Since the SR is 1.0, hard code the revision_value as * 0x1 here. This way we avoid re using the same register * that is giving us required information inside socinfo * anyway.
*/
*revision_value = 0x1; goto done;
}
ret = regmap_read(opp_data->syscon, opp_data->soc_data->rev_offset,
&revision); if (opp_data->soc_data->quirks & TI_QUIRK_SYSCON_MAY_BE_MISSING && ret == -EIO) { /* not a syscon register! */ void __iomem *regs = ioremap(OMAP3_SYSCON_BASE +
opp_data->soc_data->rev_offset, 4);
if (!regs) return -ENOMEM;
revision = readl(regs);
iounmap(regs);
} elseif (ret) {
dev_err(dev, "Failed to read the revision number from syscon: %d\n",
ret); return ret;
}
match = dev_get_platdata(&pdev->dev); if (!match) return -ENODEV;
opp_data = devm_kzalloc(&pdev->dev, sizeof(*opp_data), GFP_KERNEL); if (!opp_data) return -ENOMEM;
opp_data->soc_data = match->data;
opp_data->cpu_dev = get_cpu_device(0); if (!opp_data->cpu_dev) {
pr_err("%s: Failed to get device for CPU0\n", __func__); return -ENODEV;
}
opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev); if (!opp_data->opp_node) {
dev_info(opp_data->cpu_dev, "OPP-v2 not supported, cpufreq-dt will attempt to use legacy tables.\n"); goto register_cpufreq_dt;
}
ret = ti_cpufreq_setup_syscon_register(opp_data); if (ret) goto fail_put_node;
/* * OPPs determine whether or not they are supported based on * two metrics: * 0 - SoC Revision * 1 - eFuse value
*/
ret = ti_cpufreq_get_rev(opp_data, &version[0]); if (ret) goto fail_put_node;
ret = ti_cpufreq_get_efuse(opp_data, &version[1]); if (ret) goto fail_put_node;
if (opp_data->soc_data->multi_regulator) { if (opp_data->soc_data->reg_names)
config.regulator_names = opp_data->soc_data->reg_names; else
config.regulator_names = default_reg_names;
}
ret = dev_pm_opp_set_config(opp_data->cpu_dev, &config); if (ret < 0) {
dev_err_probe(opp_data->cpu_dev, ret, "Failed to set OPP config\n"); goto fail_put_node;
}
/* Check to ensure we are on a compatible platform */
match = ti_cpufreq_match_node(); if (match)
platform_device_register_data(NULL, "ti-cpufreq", -1, match, sizeof(*match));
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.