/* ------------------------------------------------------------------------*//** * @FUNCTION voltdm54xx_voltage_set * @BRIEF set voltage of given voltage domain * @RETURNS 0 in case of success * OMAPCONF_ERR_CPU * OMAPCONF_ERR_ARG * OMAPCONF_ERR_NOT_AVAILABLE * OMAPCONF_ERR_REG_ACCESS * OMAPCONF_ERR_INTERNAL * @param[in] id: valid voltage domain ID * @DESCRIPTION set voltage of given voltage domain *//*------------------------------------------------------------------------ */ int voltdm54xx_voltage_set(voltdm54xx_id id, unsigned long uv) { CHECK_CPU(54xx, (double) OMAPCONF_ERR_CPU); CHECK_ARG_LESS_THAN(id, VDD54XX_ID_MAX, (double) OMAPCONF_ERR_ARG); /* Retrieve domain state */ switch (id) { case VDD54XX_WKUP: return OMAPCONF_ERR_NOT_AVAILABLE; case VDD54XX_MPU: return smps_voltage_set(PMIC_SMPS_MPU, uv); break; case VDD54XX_MM: return smps_voltage_set(PMIC_SMPS_MM, uv); break; case VDD54XX_CORE: return smps_voltage_set(PMIC_SMPS_CORE, uv); break; default: return OMAPCONF_ERR_ARG; } }
/* ------------------------------------------------------------------------*//** * @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; }