Exemple #1
0
/* ------------------------------------------------------------------------*//**
 * @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;
	}
}
Exemple #2
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;
}