/* ------------------------------------------------------------------------*//** * @FUNCTION voltdm54xx_nominal_voltage_get * @BRIEF return the nominal voltage of a given voltage domain * @RETURNS supply voltage in case of success (>= 0.0) * OMAPCONF_ERR_ARG * OMAPCONF_ERR_CPU * OMAPCONF_ERR_NOT_AVAILABLE * @param[in] id: valid voltage domain ID * @DESCRIPTION return the nominal voltage of a given voltage domain. *//*------------------------------------------------------------------------ */ double voltdm54xx_nominal_voltage_get(voltdm54xx_id id) { int ret; double volt; vc54xx_registers vc_regs; unsigned char cmd_on, cmd_onlp, cmd_ret, cmd_off; CHECK_CPU(54xx, (double) OMAPCONF_ERR_CPU); CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, (double) OMAPCONF_ERR_ARG); ret = vc54xx_registers_get(&vc_regs); if (ret != 0) return (double) ret; ret = vc54xx_cmd_values_get(id, &vc_regs, &cmd_on, &cmd_onlp, &cmd_ret, &cmd_off); if (ret != 0) return (double) ret; volt = smps_vsel2volt(vdd_id2smps_id(id), cmd_on); dprintf("%s(%s): nominal volt=%lfV\n", __func__, voltdm54xx_name_get(id), volt); return volt; }
/* ------------------------------------------------------------------------*//** * @FUNCTION vc44xx_config_show * @BRIEF decode and show VC current configuration * @RETURNS 0 in case of success * OMAPCONF_ERR_CPU * OMAPCONF_ERR_REG_ACCESS * @param[in,out] stream: output file (NULL: no output (silent)) * @param[in,out] vc_regs: Voltage Controller registers content * @DESCRIPTION decode and show VC current configuration *//*------------------------------------------------------------------------ */ int vc44xx_config_show(FILE *stream, vc44xx_registers *vc_regs) { voltdm44xx_id id; unsigned char raw_cmd_on, raw_cmd_onlp, raw_cmd_ret, raw_cmd_off; unsigned char cmd_on, cmd_onlp, cmd_ret, cmd_off; char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN]; unsigned int row = 0; CHECK_CPU(44xx, OMAPCONF_ERR_CPU); row = 0; autoadjust_table_init(table); autoadjust_table_strncpy(table, row, 0, "PRM VC Configuration"); autoadjust_table_strncpy(table, row, 1, "VC_MPU"); autoadjust_table_strncpy(table, row, 2, "VC_IVA"); autoadjust_table_strncpy(table, row, 3, "VC_CORE"); row++; for (id = OMAP4_VDD_MPU; id <= OMAP4_VDD_CORE; id++) { row = 1; autoadjust_table_strncpy(table, row, 0, "Power IC Slave Address (SA)"); snprintf(table[row][id], TABLE_MAX_ELT_LEN, "0x%02X", vc44xx_sa_get(id, vc_regs->prm_vc_smps_sa, vc_regs->prm_vc_cfg_channel)); row++; autoadjust_table_strncpy(table, row, 0, "Voltage Reg. Addr (VOLRA)"); snprintf(table[row][id], TABLE_MAX_ELT_LEN, "0x%02X", vc44xx_volra_get(id, vc_regs->prm_vc_cfg_channel, vc_regs->prm_vc_smps_ra_vol)); row++; autoadjust_table_strncpy(table, row, 0, "Command Reg. Addr (CMDRA)"); snprintf(table[row][id], TABLE_MAX_ELT_LEN, "0x%02X", vc44xx_cmdra_get(id, vc_regs->prm_vc_cfg_channel, vc_regs->prm_vc_val_smps_ra_cmd)); row++; autoadjust_table_strncpy(table, row++, 0, "Command Values:"); vc44xx_raw_cmd_values_get(id, vc_regs, &raw_cmd_on, &raw_cmd_onlp, &raw_cmd_ret, &raw_cmd_off); vc44xx_cmd_values_get(id, vc_regs, &cmd_on, &cmd_onlp, &cmd_ret, &cmd_off); strncpy(table[row][0], " ON", TABLE_MAX_ELT_LEN); snprintf(table[row][id], TABLE_MAX_ELT_LEN, "0x%02X (%.6lfV)", raw_cmd_on, smps_vsel2volt(vdd_id2smps_id(id), cmd_on)); row++; autoadjust_table_strncpy(table, row, 0, " ON-Low-Power (ONLP)"); snprintf(table[row][id], TABLE_MAX_ELT_LEN, "0x%02X (%.6lfV)", raw_cmd_onlp, smps_vsel2volt(vdd_id2smps_id(id), cmd_onlp)); row++; autoadjust_table_strncpy(table, row, 0, " RET"); snprintf(table[row][id], TABLE_MAX_ELT_LEN, "0x%02X (%.6lfV)", raw_cmd_ret, smps_vsel2volt(vdd_id2smps_id(id), cmd_ret)); row++; autoadjust_table_strncpy(table, row, 0, " OFF"); snprintf(table[row][id], TABLE_MAX_ELT_LEN, "0x%02X (%.6lfV)", raw_cmd_off, smps_vsel2volt(vdd_id2smps_id(id), cmd_off)); row++; } if (stream != NULL) autoadjust_table_fprint(stream, table, row, 4); return 0; }
/* ------------------------------------------------------------------------*//** * @FUNCTION lib54xx_vminsearch * @BRIEF search minimum supply voltage by decreasing voltage * step by step until it breaks. * @RETURNS 0 on success * OMAPCONF_ERR_CPU * OMAPCONF_ERR_ARG * OMAPCONF_ERR_NOT_AVAILABLE * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_INTERNAL * @param[in] argc: shell input argument number (must be == 3) * @param[in] argv: shell input argument(s) * argv[0]="voltage domain" ("mpu", "mm", "core") * argv[1]="initial voltage" (in volts) * argv[2]="delay" between steps (in milliseconds) * @DESCRIPTION search minimum supply voltage by decreasing voltage * step by step until it breaks. * NB: switch CPUFreq governor to "userspace" & * disable smart-reflex *//*------------------------------------------------------------------------ */ int lib54xx_vminsearch(int argc, char *argv[]) { long uv; double v, prev_v; int ret, temp; unsigned long vstep; unsigned char vsel; voltdm54xx_id vdd_id; sr54xx_mod_id sr_id; unsigned int ms; char prev_gov[CPUFREQ_GOV_MAX_NAME_LENGTH]; CHECK_CPU(54xx, OMAPCONF_ERR_CPU); /* Retrieve arguments */ if (argc != 3) goto lib54xx_vminsearch_arg_err; if (strcmp(argv[0], "mpu") == 0) vdd_id = VDD54XX_MPU; else if (strcmp(argv[0], "mm") == 0) vdd_id = VDD54XX_MM; else if (strcmp(argv[0], "core") == 0) vdd_id = VDD54XX_CORE; else goto lib54xx_vminsearch_arg_err; ret = sscanf(argv[1], "%lf", &v); if (ret != 1) goto lib54xx_vminsearch_arg_err; ret = sscanf(argv[2], "%d", &ms); if (ret != 1) goto lib54xx_vminsearch_arg_err; if (ms <= 0) goto lib54xx_vminsearch_arg_err; /* * Switch governor to 'userspace' otherwise voltage change will be * overriden in case of OPP change. */ printf("Warning: switching CPUFreq governor to 'userspace', otherwise " "voltage change will be overriden...\n"); ret = cpufreq_scaling_governor_set("userspace", prev_gov); if (ret < 0) printf("Warning: failed to switch governor. Voltage will be " "overriden in case of OPP change.\n"); else printf("CPUFreq governor switched to 'userspace'.\n"); /* * Disable Smart-Reflex (if running) otherwise voltage change will be * overriden. */ sr_id = sr54xx_vddid2srid(vdd_id); if (sr54xx_avs_is_enabled(sr_id)) { printf("Warning: %s Smart-Reflex AVS is enabled. " "Disabling it...\n", voltdm54xx_name_get(vdd_id)); ret = sr54xx_avs_enable(sr_id, 0); if (ret == 0) printf("Smartreflex disabled.\n\n"); else printf("Warning: Could not disable Smart-Reflex AVS. " "Voltage may be overriden.\n\n"); } else { printf("Smartreflex disabled.\n\n"); } /* Show current OPP for reference */ printf("Current OPP configuration for reference:\n\n"); opp_show(stdout); /* Retrieving SMPS voltage step */ vstep = smps_step_get(vdd_id2smps_id(vdd_id)); dprintf("%s(): vstep=%luuV\n", __func__, vstep); printf("Vmin SEARCH on %s domain scaling voltage down from %1.3lfV in " "steps of %lumV, waiting %dms between each step.\n", voltdm54xx_name_get(vdd_id), v, vstep / 1000, ms); printf("LAST voltage displayed with OK status before crash " "will be the Vmin for %s domain.\n\n", voltdm54xx_name_get(vdd_id)); printf("NB:\n - Make sure your load generator application is " "running in background during the whole procedure.\n"); printf(" - PLATFORM MUST BE REBOOTED AFTER USE " "(NO POSSIBLE RECOVERY).\n\n"); /* Rounding requested initial voltage */ vsel = smps_uvolt2vsel(vdd_id2smps_id(vdd_id), (unsigned long) (v * 1000000)); prev_v = v; v = (double) smps_vsel2uvolt(vdd_id2smps_id(vdd_id), vsel); v = v / 1000000; if (v != prev_v) printf("Note: rounded up initial voltage to %.3lfV.\n\n", v); /* Decreasing voltage step by step until it breaks */ printf("Starting Vmin SEARCH...\n"); for (uv = (unsigned long) (v * 1000000); uv >= 0; uv = uv - vstep) { /* Get vsel corresponding to target voltage */ vsel = smps_uvolt2vsel(vdd_id2smps_id(vdd_id), uv); temp = temp54xx_get(voltdm2sensor_id(vdd_id)); if (temp != TEMP_ABSOLUTE_ZERO) printf("Trying %1.3lfV (SMPS code: 0x%02X, temperature: %dC/%dF)...", smps_vsel2volt(vdd_id2smps_id(vdd_id), vsel), vsel, temp, celcius2fahrenheit(temp)); else printf("Trying %1.3lfV (SMPS code: 0x%02X, temperature: N/A)...", smps_vsel2volt(vdd_id2smps_id(vdd_id), vsel), vsel); fflush(stdout); ret = smps_voltage_set(vdd_id2smps_id(vdd_id), uv); if (ret != 0) { fprintf(stderr, "Error: could not set %s voltage!\n\n", voltdm54xx_name_get(vdd_id)); return ret; } usleep(1000 * ms); printf("OK!\n"); } fprintf(stderr, "Shouldn't have reached this point... " "please check voltage is really scaling down.\n\n"); return 0; lib54xx_vminsearch_arg_err: return err_arg_msg_show(HELP_VOLT); return OMAPCONF_ERR_ARG; }