Beispiel #1
0
/* ------------------------------------------------------------------------*//**
 * @FUNCTION		temp_sensor_show
 * @BRIEF		display all available temperatures formatted in a table.
 * @RETURNS		temperatures formatted in a table
 *			OMAPCONF_ERR_CPU
 *			OMAPCONF_ERR_ARG
 *			OMAPCONF_ERR_INTERNAL
 *			OMAPCONF_ERR_NOT_AVAILABLE
 * @param[in,out]	stream: output file
 * @param[in,out]	sensor: generic temperature sensor name
 *				Use "all" to show all temperatures
 * @param[in]		hw: use s/w (driver based) read or hw_sensor read?
 * @DESCRIPTION		display all available temperatures formatted in a table.
 *			Display both Celcius and Fahrenheit degrees.
 *//*------------------------------------------------------------------------ */
static int _temp_sensor_show(FILE *stream, const char *sensor, const char hw)
{
	char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN];
	unsigned int row = 0;
	int i, count, temp, temp_f;
	char temp_s[EMIF_TEMP_MAX_NAME_LENGTH];
	const char sensor2[TEMP_SENSOR_MAX_NAME_LENGTH];
	const genlist *list;

	CHECK_NULL_ARG(stream, OMAPCONF_ERR_ARG);
	CHECK_NULL_ARG(sensor, OMAPCONF_ERR_ARG);

	if (strcasecmp(sensor, "all") != 0) {
		if (!temp_sensor_is_available(sensor)) {
			fprintf(stderr,
				"omapconf: '%s' temperature sensor is not available!\n",
				sensor);
			return OMAPCONF_ERR_NOT_AVAILABLE;
		}
		if (hw)
			temp = hwtemp_sensor_get(sensor);
		else
			temp = temp_sensor_get(sensor);
		if (temp == TEMP_ABSOLUTE_ZERO) {
			fprintf(stderr,
				"omapconf: could not retrieve '%s' temperature!\n",
				sensor);
			return OMAPCONF_ERR_INTERNAL;
		} else if ((strcasecmp(sensor, TEMP_SENSOR_MEM1) == 0) ||
				(strcasecmp(sensor, TEMP_SENSOR_MEM2) == 0)) {
			fprintf(stream, "%s\n",
				emif_mr4_convert((emif_mr4_code) temp,
					TEMP_CELCIUS_DEGREES));
			return 0;
		} else {
			fprintf(stream, "%d\n", temp);
			return 0;
		}
	}

	/* Retrieve temperature sensor list */
	list = temp_sensor_list_get();
	if (list == NULL) {
		fprintf(stderr, "omapconf: CPU not yet supported, sorry...\n");
		return OMAPCONF_ERR_INTERNAL;
	}

	/* Retrieve temperature sensor list count */
	count = temp_sensor_count_get();
	if (count <= 0) {
		fprintf(stderr, "omapconf: could not retrieve sensor count!\n");
		return OMAPCONF_ERR_INTERNAL;
	}
	dprintf("found %d temperature sensors\n", count);

	/* Fill table header */
	row = 0;
	autoadjust_table_init(table);
	autoadjust_table_strncpy(table, row, 0, "Sensor");
	autoadjust_table_strncpy(table, row, 1, "Temperature (C)");
	autoadjust_table_strncpy(table, row++, 2, "Temperature (F)");

	/* Fill table with temperatures */
	for (i = 0; i < count; i++) {
		genlist_get((genlist *) list, i, (char *) &sensor2);
		if (sensor2 == NULL) {
			fprintf(stderr,
				"omapconf: could not retrieve sensor!\n");
			return OMAPCONF_ERR_INTERNAL;
		}
		autoadjust_table_strncpy(table, row, 0, (char *) sensor2);
		dprintf("%s(): sensor is %s\n", __func__, sensor2);
		if (hw)
			temp = hwtemp_sensor_get(sensor2);
		else
			temp = temp_sensor_get(sensor2);
		if (temp != TEMP_ABSOLUTE_ZERO) {
			if ((strcasecmp(sensor2, TEMP_SENSOR_MEM1) == 0) ||
				(strcasecmp(sensor2, TEMP_SENSOR_MEM2) == 0)) {
				sprintf(temp_s, "%s",
					emif_mr4_convert((emif_mr4_code) temp,
						TEMP_CELCIUS_DEGREES));
				autoadjust_table_strncpy(table, row, 1, temp_s);
				sprintf(temp_s, "%s",
					emif_mr4_convert((emif_mr4_code) temp,
						TEMP_FAHRENHEIT_DEGREES));
				autoadjust_table_strncpy(table, row++, 2,
					temp_s);
			} else {
				sprintf(temp_s, "%d", temp);
				autoadjust_table_strncpy(table, row, 1, temp_s);
				temp_f = celcius2fahrenheit(temp);
				sprintf(temp_s, "%d", temp_f);
				autoadjust_table_strncpy(table, row++, 2,
					temp_s);
			}
		} else {
			autoadjust_table_strncpy(table, row, 1, "NA");
			autoadjust_table_strncpy(table, row++, 2, "NA");
		}
	}

	/* Display table */
	return autoadjust_table_fprint(stream, table, row, 3);
}
Beispiel #2
0
/**
 * Function: counters44xx_perf
 * Role: trace OMAP performance (CPU Load, OPP & memory bandwidth usage).
 * Parameters:
 *	capture_time: capture (trace) duration
 * Return:
 *	0 in case of success
 *	OMAPCONF_ERR_ARG
 *	OMAPCONF_ERR_NOT_AVAILABLE
 *	OMAPCONF_ERR_UNEXPECTED
 */
int counters44xx_count(unsigned int capture_time)
{

	unsigned int i;
	unsigned int sample_cnt;
	int ret;
	unsigned int addr, data, l2_disabled_prior = 0;
	unsigned int *trace_buf[TRACE_CFG_ENABLED_OPTIONS_MAX];
	unsigned short emif;
	unsigned int sample;
	FILE *fp = NULL;
	char s[16];
	char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN];
	unsigned int row = 0;
	char name[64];
	char tmp_name[64];
	char option[64];
	unsigned int temp, avg, min, max;


	/* Configure EMIF counters */
	ret = 0;
	if (trace_state[TRACE_CFG_EMIF0_CNT0_FILTER] >= 0)
		ret = emif44xx_perf_cnt_configure(EMIF44XX_0, 0,
			trace_state[TRACE_CFG_EMIF0_CNT0_FILTER],
			trace_state[TRACE_CFG_EMIF0_CNT0_ID],
			trace_state[TRACE_CFG_EMIF0_CNT0_ADDRSPACE]);
	if (trace_state[TRACE_CFG_EMIF1_CNT0_FILTER] >= 0)
		ret |= emif44xx_perf_cnt_configure(EMIF44XX_1, 0,
			trace_state[TRACE_CFG_EMIF1_CNT0_FILTER],
			trace_state[TRACE_CFG_EMIF1_CNT0_ID],
			trace_state[TRACE_CFG_EMIF1_CNT0_ADDRSPACE]);
	if (trace_state[TRACE_CFG_EMIF0_CNT1_FILTER] >= 0)
		ret |= emif44xx_perf_cnt_configure(EMIF44XX_0, 1,
			trace_state[TRACE_CFG_EMIF0_CNT1_FILTER],
			trace_state[TRACE_CFG_EMIF0_CNT1_ID],
			trace_state[TRACE_CFG_EMIF0_CNT1_ADDRSPACE]);
	if (trace_state[TRACE_CFG_EMIF1_CNT1_FILTER] >= 0)
		ret |= emif44xx_perf_cnt_configure(EMIF44XX_1, 1,
			trace_state[TRACE_CFG_EMIF1_CNT1_FILTER],
			trace_state[TRACE_CFG_EMIF1_CNT1_ID],
			trace_state[TRACE_CFG_EMIF1_CNT1_ADDRSPACE]);

	if (ret != 0) {
		fprintf(stderr, "%s(): error while configuring EMIF perf. "
			"counters!\n", __func__);
		ret = OMAPCONF_ERR_NOT_AVAILABLE;
		goto counters44xx_count_err;
	}

	/* Configure L2CC counters */
	/* Do this regardless whether enabled or disabled (at this point.) */
	if (trace_state[TRACE_CFG_L2CC_CNT0_FILTER] >= 0)
		ret = l2cc44xx_perf_cnt_configure(0, trace_state[TRACE_CFG_L2CC_CNT0_FILTER], 1); /* for last entry, should use boolean 'true' */
	if (trace_state[TRACE_CFG_L2CC_CNT1_FILTER] >= 0)
		ret = l2cc44xx_perf_cnt_configure(1, trace_state[TRACE_CFG_L2CC_CNT1_FILTER], 1); /* for last entry, should use boolean 'true' */

/*
//	if (ret != 0) {
//		fprintf(stderr, "%s(): error while configuring L2CC perf. "
//			"counters!\n", __func__);
//		ret = OMAPCONF_ERR_NOT_AVAILABLE;
//		goto counters44xx_count_err;
//		}
*/

	/* Allocate buffer to store sampled data, unless continuous capture is enabled */
	if (capture_time > 0) {
		if (sampling_rate > 0) {
			sample_cnt = 1 + ((capture_time * 1000) / sampling_rate);
		} else {
	/* If smaple rate of 0, trace as fast as possible for the capture time. */
			sample_cnt = 1 + ((capture_time * 1000));
		}
	} else {
		/* Hack. If capture_time == 0, capture continuous. Need room for at least 2 samples. */
		sample_cnt = 2;

		if (trace_state[TRACE_CFG_LONG_HEADER] == 1) {
			printf("#\n");
			printf("# ----------------- OMAP4430 Performance Trace+ ----------"
				"--------------------------------------------------------------"
				"-----\n");
			printf("#\n");
		/*	printf("# NB:\n"); */
			printf("#   * This is an intrusive trace (counters polling).\n");
			printf("#     Idle C-States usage was altered.\n");
			printf("#     Limted additional CPU & EMIFs loads generated.\n");
			printf("#\n");
		/*	printf("#   * If CPU1 Load = -5.0, it means CPU1 is OFFLINE.\n"); */
		/*	printf("#\n"); */
		/*	printf("#   * CPU LOADS CANNOT be directly converted to Mhz.\n"); */
		/*	printf("#     OPP may have changed during the audit.\n"); */
		/*	printf("#\n"); */
			printf("# ----------------------- Trace FORMAT -------------------"
				"--------------------------------------------------------------"
				"-----\n");
			printf("#\n");
			printf("# Trace Length: %us\n", capture_time);
			printf("#\n");
			printf("# Trace Sampling Rate: %ums\n",
				sampling_rate);
			printf("#\n");

			printf("# Number of samples: %u\n", sample_cnt - 1);
			printf("#\n");
			printf("# %10.10s ", "Timestamp(s)");
		};
		for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
			if (trace_state[i] >= 0) {/* Traces state is enabled if non-zero state value. */
				ret = value2name(i, name, trace_config_options_table);
				printf("\t%10.10s", name);
				switch (i) {
				case TRACE_CFG_EMIF0_CNT0_FILTER:
				case TRACE_CFG_EMIF1_CNT0_FILTER:
				case TRACE_CFG_EMIF0_CNT1_FILTER:
				case TRACE_CFG_EMIF1_CNT1_FILTER:
					ret = value2name(trace_state[i], name, emif_event_counters);
					ret = snprintf(tmp_name, 64, "%s%s", ".", name);
					ret = snprintf(name, 64, "%s", tmp_name);
					break;
				case TRACE_CFG_L2CC_CNT0_FILTER:
				case TRACE_CFG_L2CC_CNT1_FILTER:
					ret = value2name(trace_state[i], name, l2cc_event_counters_table);
					ret = snprintf(tmp_name, 64, "%s%s", ".", name);
					ret = snprintf(name, 64, "%s", tmp_name);
					break;
				default:
					strcpy(name, " ");
					break;
				} /* end switch */
				printf("%s ", name);
			}
		}
		printf("\n");

		if (trace_state[TRACE_CFG_LONG_HEADER] == 1) {
			printf("#\n");
			printf("# ----------------------- Trace START --------------------"
				"--------------------------------------------------------------"
				"-----\n");
		}
	}

	dprintf("%s(): capture_time=%us, sample_cnt=%u\n", __func__,
		capture_time, sample_cnt);


	for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
		if (trace_state[i] >= 0) {/* Traces state is enabled if non-zero state value. */
			/* Add three sample entries to hold min, avg, max */
			trace_buf[i] = malloc((sample_cnt+3) * sizeof(unsigned int));
			if (trace_buf[i] == NULL) {
				ret = value2name(i, name, trace_config_options_table);
				fprintf(stderr, "%s(): could not allocate %s!\n",
					__func__, name);
				ret = OMAPCONF_ERR_NOT_AVAILABLE;
				goto counters44xx_count_err;
			}
		}
	} /* end for i < TRACE_CFG_ENABLED_OPTIONS_MAX */

	/* Enable L2CC counters */
	ret = l2cc44xx_perf_cnt_enable();


	/* Sample performance indicators periodically */
	printf("\n");

	printf("Sampling OMAP Counters for %us, please wait...\n",
		capture_time);


	for (sample = 0; sample < sample_cnt; sample++) {

/*
		// This could be a big for loop and 'switch' statemenet...
		// Get CPU runtime execution stats
		// Get EMIF cnt0, cnt1 & total mclk cycle counts as enabled
		// skorson
		// Being lazy and doing these two one after the other. I suppose code could be written
		// to convert a for 0 to 1 loop but with only two, this is OK.
*/


		emif = 0;
		if (trace_state[TRACE_CFG_EMIF0_CNT0_FILTER] >= 0) {
			trace_buf[TRACE_CFG_EMIF0_CNT0_FILTER][sample] = emif44xx_perf_cnt_get_count(
				emif, EMIF44XX_PERF_CNT_0);
			dprintf("%s(): EMIF0 counter 0 value=%u\n", __func__,
				trace_buf[TRACE_CFG_EMIF0_CNT0_FILTER][sample]);
		}
		if (trace_state[TRACE_CFG_EMIF0_CNT1_FILTER] >= 0) {
			trace_buf[TRACE_CFG_EMIF0_CNT1_FILTER][sample] = emif44xx_perf_cnt_get_count(
				emif, EMIF44XX_PERF_CNT_1);
			dprintf("%s(): EMIF0 counter 1 value=%u\n", __func__,
				trace_buf[TRACE_CFG_EMIF0_CNT1_FILTER][sample]);
		}

		if (trace_state[TRACE_CFG_EMIF0_MCLK_CYCLES] >= 0) {
			trace_buf[TRACE_CFG_EMIF0_MCLK_CYCLES][sample] = emif44xx_perf_cnt_get_time(emif);
		}

		emif = 1;
		if (trace_state[TRACE_CFG_EMIF1_CNT0_FILTER] >= 0) {
			trace_buf[TRACE_CFG_EMIF1_CNT0_FILTER][sample] = emif44xx_perf_cnt_get_count(
				emif, EMIF44XX_PERF_CNT_0);
			dprintf("%s(): EMIF1 counter 0 value=%u\n", __func__,
				trace_buf[TRACE_CFG_EMIF1_CNT0_FILTER][sample]);
		}
		if (trace_state[TRACE_CFG_EMIF1_CNT1_FILTER] >= 0) {
			trace_buf[TRACE_CFG_EMIF1_CNT1_FILTER][sample] = emif44xx_perf_cnt_get_count(
				emif, EMIF44XX_PERF_CNT_1);
			dprintf("%s(): EMIF1 counter 1 value=%u\n", __func__,
				trace_buf[TRACE_CFG_EMIF1_CNT1_FILTER][sample]);
		}

		if (trace_state[TRACE_CFG_EMIF1_MCLK_CYCLES] >= 0) {
			trace_buf[TRACE_CFG_EMIF1_MCLK_CYCLES][sample] = emif44xx_perf_cnt_get_time(emif);
			dprintf("%s(): EMIF1 MCLK cycles=%u\n", __func__,
				trace_buf[TRACE_CFG_EMIF1_MCLK_CYCLES][sample]);
		}


/*
// FIXME: There is a bug where the L2 Counters are being disabled. Until this is known, enable the following
// block to determine if the counter has been disabled during a run. Print appropriate ERROR to screen...
*/
		if ((trace_state[TRACE_CFG_L2CC_CNT0_FILTER] >= 0) || (trace_state[TRACE_CFG_L2CC_CNT1_FILTER] >= 0))  {


			/* check if counter is still enabled.... */
			ret = name2addr("EVENT_COUNTER_CONTROL", &addr,
				(reg_table *) omap4_mpuss_pl310_reg_table);
			ret = mem_read(addr, &data);
			dprintf("EVENT COUNTER VALUE: 0x%x 0x%x\n", addr, data);
			if (ret != 0) {
				fprintf(stderr, "%s(): error reading L2CC (PL310) EVENT_COUNTER_CONTROL reg!\n",
				__func__);
				return OMAPCONF_ERR_REG_ACCESS;
			}
			if (data == 0  && l2_disabled_prior == 0) {
				l2_disabled_prior = 1;
				fprintf(stderr, "%s(): WARNING:L2CC (PL310) EVENT_COUNTER_CONTROL was DISABLED during a run!!!\n",
				__func__);
				fprintf(stderr, "%s(): WARNING:  Counter values will be invalid (zero) after this point.\n",
				__func__);
			}
		}

/* END FIXME */



		if (trace_state[TRACE_CFG_L2CC_CNT0_FILTER] >= 0) {
			trace_buf[TRACE_CFG_L2CC_CNT0_FILTER][sample] =
				(unsigned int) l2cc44xx_get_perf_cnt(0);
			dprintf("%s(): l2_event_cnt[0] sample %d = 0x%x %d\n", __func__, sample,
				trace_buf[TRACE_CFG_L2CC_CNT0_FILTER][sample], trace_buf[TRACE_CFG_L2CC_CNT0_FILTER][sample]);
		}
		if (trace_state[TRACE_CFG_L2CC_CNT1_FILTER] >= 0) {
			trace_buf[TRACE_CFG_L2CC_CNT1_FILTER][sample] =
				(unsigned int) l2cc44xx_get_perf_cnt(1);
			dprintf("%s(): l2_event_cnt[1] sample %d = 0x%x %d\n", __func__, sample,
				trace_buf[TRACE_CFG_L2CC_CNT1_FILTER][sample], trace_buf[TRACE_CFG_L2CC_CNT1_FILTER][sample]);
		}

		if (trace_state[TRACE_CFG_TIMER_32K_SYNC] >= 0) {
			addr = T32KSYNCNT_CR;
			ret = mem_read(addr, &data);
			trace_buf[TRACE_CFG_TIMER_32K_SYNC][sample] = data;
			dprintf("%s(): 32K CLK cycles=%u\n", __func__,
				trace_buf[TRACE_CFG_TIMER_32K_SYNC][sample]);
		}
		dprintf("\n");
		/* Sleep for some [minimum] time before sampling again */



		if ((capture_time == 0) && (sample > 0)) {
			/* Save timestamp */
			printf("[unix time stamp here]");
			for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
				if (trace_state[i] >= 0) {
					sprintf(s, "%u", count32_delta(trace_buf[i][0],
					trace_buf[i][1]));
					printf("\t%10.10s", s);
				} /* if state >= 0 */
			} /* for i to TRACE_CFG_ENABLED_OPTIONS_MAX */
			printf("\n");

			/* Now move sample[1] to sample[0] */
			for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
				if (trace_state[i] >= 0) {
					trace_buf[i][0] = trace_buf[i][1];
				} /* if state >= 0 */
			} /* for i to TRACE_CFG_ENABLED_OPTIONS_MAX */
			sample = 0;
		}

		/* SLeep onyl if a sampling rate is set. */
		/* Sampling rate of 0 is as fast as possible... */
		if (sampling_rate > 0)
			usleep(sampling_rate * 1000);
	}

	/* Disable L2CC counters */
	/* Do regardless of whether enabled for tracing or not. */
	ret = l2cc44xx_perf_cnt_disable();

	printf("Sampling done, processing and saving data...\n");

	/* Open trace output file */
	fp = workdir_fopen(trace_perf_file, "w");
	if (fp == NULL) {
		fprintf(stderr, "%s(): could not create %s!\n",
			__func__, trace_perf_file);
		ret = OMAPCONF_ERR_NOT_AVAILABLE;
		goto counters44xx_count_err;
	}

	dprintf("INFO: TRACE_CFG_LONG_HEADER %d\n", trace_state[TRACE_CFG_LONG_HEADER]);

	if (trace_state[TRACE_CFG_LONG_HEADER] == 1) {
		fprintf(fp, "#\n");
		fprintf(fp, "# ----------------- OMAP4430 Performance Trace+ ----------"
			"--------------------------------------------------------------"
			"-----\n");
		fprintf(fp, "#\n");
	/*	fprintf(fp, "# NB:\n"); */
		fprintf(fp, "#   * This is an intrusive trace (counters polling).\n");
		fprintf(fp, "#     Idle C-States usage was altered.\n");
		fprintf(fp, "#     Limted additional CPU & EMIFs loads generated.\n");
		fprintf(fp, "#\n");
	/*	fprintf(fp, "#   * If CPU1 Load = -5.0, it means CPU1 is OFFLINE.\n"); */
	/*	fprintf(fp, "#\n"); */
	/*	fprintf(fp, "#   * CPU LOADS CANNOT be directly converted to Mhz.\n"); */
	/*	fprintf(fp, "#     OPP may have changed during the audit.\n"); */
	/*	fprintf(fp, "#\n"); */
		fprintf(fp, "# ----------------------- Trace FORMAT -------------------"
			"--------------------------------------------------------------"
			"-----\n");
		fprintf(fp, "#\n");
		fprintf(fp, "# Trace Length: %us\n", capture_time);
		fprintf(fp, "#\n");
		fprintf(fp, "# Trace Sampling Rate: %ums\n",
			sampling_rate);
		fprintf(fp, "#\n");

		fprintf(fp, "# Number of samples: %u\n", sample_cnt - 1);
		fprintf(fp, "#\n");
		fprintf(fp, "# %10.10s ", "Timestamp(s)");
	};

	for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
		if (trace_state[i] >= 0) {/* Traces state is enabled if non-zero state value. */
			ret = value2name(i, name, trace_config_options_table);
			fprintf(fp, "\t%10.10s", name);
			switch (i) {
			case TRACE_CFG_EMIF0_CNT0_FILTER:
			case TRACE_CFG_EMIF1_CNT0_FILTER:
			case TRACE_CFG_EMIF0_CNT1_FILTER:
			case TRACE_CFG_EMIF1_CNT1_FILTER:
				ret = value2name(trace_state[i], name, emif_event_counters);
				ret = snprintf(tmp_name, 64, "%s%s", ".", name);
				ret = snprintf(name, 64, "%s", tmp_name);
				break;
			case TRACE_CFG_L2CC_CNT0_FILTER:
			case TRACE_CFG_L2CC_CNT1_FILTER:
				ret = value2name(trace_state[i], name, l2cc_event_counters_table);
				ret = snprintf(tmp_name, 64, "%s%s", ".", name);
				ret = snprintf(name, 64, "%s", tmp_name);
				break;
			default:
				strcpy(name, " ");
				break;
			} /* end switch */
			fprintf(fp, "%s ", name);
		}
	}
	fprintf(fp, "\n");
	if (trace_state[TRACE_CFG_LONG_HEADER] == 1) {
		fprintf(fp, "#\n");
		fprintf(fp, "# ----------------------- Trace START --------------------"
			"--------------------------------------------------------------"
			"-----\n");
	}
	dprintf ("I'm here 0\n");

	/* Note: dropping first sample (or using it to normalize data to 0) */
	for (sample = 1; sample < sample_cnt; sample++) {
		if (sampling_rate > 0) {
		/* Save timestamp */
		sprintf(s, "%.3lf", (double)
			(sample * sampling_rate) / 1000.0);
		fprintf(fp, "%10.10s", s);
		} else {
		  sprintf(s, "%.3lf", (double)
			(sample));
		fprintf(fp, "%10.10s", s);
		}

		dprintf ("I'm here 1.%d\n", sample);

		for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
			if (trace_state[i] >= 0) {

/*
// For now, treating this timer as a counter - its easier to perform calculations
// (std. dev, mean, error etc.)
//				if (	i == TRACE_CFG_TIMER_32K_SYNC ) {
//					// These don't need offset adjusted like counters
//					sprintf(s, "%u", count32_delta(trace_buf[i][0],
//						trace_buf[i][sample]) );
//					fprintf(fp, "\t%10.10s", s);
//					continue;
//				}
*/

				dprintf("INFO: Current Sample %d Value %d Previous %d\n",
					sample, trace_buf[i][sample], trace_buf[i][sample - 1]);

				sprintf(s, "%u",
					count32_delta(trace_buf[i][sample - 1],
					trace_buf[i][sample]));
				fprintf(fp, "\t%10.10s", s);
			} /* if state >= 0 */
		} /* for i to TRACE_CFG_ENABLED_OPTIONS_MAX */

		dprintf ("I'm here 2\n");
		fprintf(fp, "\n");
	} /* for sample < sample_cnt */

	if (trace_state[TRACE_CFG_LONG_HEADER]) {
		fprintf(fp, "# ------------------------ Trace END ---------------------"
			"--------------------------------------------------------------"
			"-----\n");
	};
	fclose(fp);
	printf("Performance trace saved into \"%s\" file.\n",
		trace_perf_file);



	/* Calculate Averages/Statistics*/
	fp = workdir_fopen(trace_perf_stats_file, "w");
	if (fp == NULL) {
		fprintf(stderr, "%s(): could not create %s!\n",
			__func__, trace_perf_stats_file);
		ret = OMAPCONF_ERR_NOT_AVAILABLE;
		goto counters44xx_count_err;
	}
	dprintf ("I'm here 2\n");
	autoadjust_table_init(table);
	row = 0;
	strncpy(table[row][0], "Performance Statistics", TABLE_MAX_ELT_LEN);
	strncpy(table[row][1], "Option", TABLE_MAX_ELT_LEN);
	strncpy(table[row][2], "Min", TABLE_MAX_ELT_LEN);
	strncpy(table[row][3], "Max", TABLE_MAX_ELT_LEN);
	strncpy(table[row][4], "Average", TABLE_MAX_ELT_LEN);
	row++;

	/* Note: sample_cnt+0 = min, +1=avg, +2 = max */
	min = sample_cnt;
	avg = sample_cnt+1;
	max = sample_cnt+2;


	dprintf ("I'm here 3\n");
	for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
		/* Whats the 'if' below for? Will always be true... */
		if (trace_state[i] >= 0) {
			trace_buf[i][min] = ~0;
			trace_buf[i][max] =  0;
			trace_buf[i][avg] =  0;
			dprintf ("I'm here 3.%d\n", i);
			ret = value2name(i, name, trace_config_options_table);
			dprintf ("Name: %s MIN: %d MAX: %d AVG: %d\n", name, trace_buf[i][min], trace_buf[i][max], trace_buf[i][avg]);
			for (sample = 1; sample < sample_cnt; sample++) {
	dprintf ("I'm here 3.%d.%d\n", i, sample);
				temp = count32_delta(trace_buf[i][sample - 1],
					trace_buf[i][sample]);
	dprintf ("I'm here 3.%d.%d !FREQ %d\n", i, sample, temp);
				if (temp > trace_buf[i][max])
					trace_buf[i][max] = temp;
				if (temp < trace_buf[i][min])
					trace_buf[i][min] = temp;
				trace_buf[i][avg] = (unsigned int) avg_recalc((double) trace_buf[i][avg],
					(double) temp, sample - 1);
				ret = value2name(i, name, trace_config_options_table);
				dprintf ("Name: %s MIN: %d MAX: %d AVG: %d\n", name, trace_buf[i][min], trace_buf[i][max], trace_buf[i][avg]);
			} /* for sample < sample_cnt */
			dprintf ("I'm here 4.%d\n", i);
			/* Save statistics */
			ret = value2name(i, name, trace_config_options_table);
			dprintf ("Name: %s MIN: %d MAX: %d AVG: %d\n", name, trace_buf[i][min], trace_buf[i][max], trace_buf[i][avg]);
			strncpy(table[row][0], name, TABLE_MAX_ELT_LEN);


			strcpy (option, "");
			switch (i) {
			case TRACE_CFG_EMIF0_CNT0_FILTER:
			case TRACE_CFG_EMIF1_CNT0_FILTER:
			case TRACE_CFG_EMIF0_CNT1_FILTER:
			case TRACE_CFG_EMIF1_CNT1_FILTER:
				ret = value2name(trace_state[i], option, emif_event_counters);
				break;
			case TRACE_CFG_L2CC_CNT0_FILTER:
			case TRACE_CFG_L2CC_CNT1_FILTER:
				ret = value2name(trace_state[i], option, l2cc_event_counters_table);
				break;
			default:
				break;
			} /* end switch */
			strncpy(table[row][1], option, TABLE_MAX_ELT_LEN);
			snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%.2d", trace_buf[i][min]);
			snprintf(table[row][3], TABLE_MAX_ELT_LEN, "%.2d", trace_buf[i][max]);
			snprintf(table[row][4], TABLE_MAX_ELT_LEN, "%.2d", trace_buf[i][avg]);
			row++;
		} /* if (trace_state[i] >= 0 */

	} /* for i to TRACE_CFG_ENABLED_OPTIONS_MAX */
	dprintf ("I'm here 5\n");


	autoadjust_table_fprint(fp, table, row, 4);
	fclose(fp);
	printf("Performance statistics saved into \"%s\" file.\n\n",
		trace_perf_stats_file);
	dprintf ("I'm here 6\n");
	autoadjust_table_print(table, row, 4);
	dprintf ("I'm here 7\n");
	return ret;

counters44xx_count_err:
	/* Free allocated buffers */
	for (i = 0; i < TRACE_CFG_ENABLED_OPTIONS_MAX; i++) {
		if (trace_state[i] >= 0) {/* Traces state is enabled if non-neg state value. */
			if (trace_buf[i] != NULL) {
				free(trace_buf[i]);
			}
		}
	} /* end for i < TRACE_CFG_ENABLED_OPTIONS_MAX */

	return ret;
}
Beispiel #3
0
/* ------------------------------------------------------------------------*//**
 * @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;
}
Beispiel #4
0
/* ------------------------------------------------------------------------*//**
 * @FUNCTION		audit_performances
 * @BRIEF		audit performances (CPU Load, C-States, OPP,
 *			memory bandwidth, timers, interrrupts, ...).
 * @RETURNS		0 in case of success
 *			OMAPCONF_ERR_CPU
 *			OMAPCONF_ERR_ARG
 *			OMAPCONF_ERR_NOT_AVAILABLE
 * @param[in]		stream: output file (NULL: no output (silent))
 * @param[in]		duration: audit duration, in seconds (>= 1).
 * @param[in]		delay: initial wait delay before starting audit (in sec)
 * @DESCRIPTION		audit performance (CPU Load, C-States, OPP,
 *			memory bandwidth, timers, interrrupts, ...).
 *//*------------------------------------------------------------------------ */
int audit_performances(FILE *stream, unsigned int duration, unsigned int delay)
{
	int ret;
	unsigned short skip_proc_stats_audit;
	unsigned int cpu_cores_cnt, cpu_online_cores_cnt;
	unsigned short *cpu_online;
	unsigned int *idle_t0, *iowait_t0, *sum_t0;
	unsigned int *idle_t1, *iowait_t1, *sum_t1;
	unsigned int *idle_cnt, *iowait_cnt, *sum_cnt;
	double *load, load_total;
	unsigned int cstates_nbr;
	uint64_t cstates_usage[MAX_CSTATE][3];
	uint64_t cstates_time[MAX_CSTATE][3];
	unsigned short emif;
	unsigned int emif_busy_cycles[2];
	unsigned int emif_cycles[2];
	unsigned int emif_delta_cycles,
		emif_delta_busy_cycles;
	double emif_load;
	uint64_t *time_in_opp_t0 = NULL;
	uint64_t *time_in_opp_t1 = NULL;
	uint64_t *time_in_opp_cnt = NULL;
	uint64_t total_trans_t0, total_trans_t1, total_trans_cnt;
	unsigned int i;
	uint64_t sec, msec, usec, active_c0_time;
	double pct;
	char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN];
	unsigned int row = 0;
	char name[16];
	FILE *fp = NULL;
	char perf_summary_file[64];
	FILE *fp_irq_1, *fp_irq_2, *fp_timerstats;
	unsigned int irq_total_count, occurred_irq_count, timer_count;
	genlist occurred_irq_list, timerstats_list;
	irq_info irq_inf;
	timerstat_info timer_inf;
	char irq_snap_file1[32];
	char irq_snap_file2[32];
	char timerstats_file[32];
	char timerstats_summary[256];
	unsigned int skip_irq_audit, skip_cstate_audit;
	int skip_timerstats_audit;
	char *workdir;
	unsigned short skip_cpufreq_audit;
	unsigned int opp_cnt;


	if (duration == 0) {
		fprintf(stream, "Duration should be at least 1 second ...\n\n");
		ret = OMAPCONF_ERR_ARG;
		goto audit_performances_exit;
	}

	if (!cpu_is_omap44xx() && !cpu_is_omap54xx()) {
		fprintf(stream, "Unsupported platform, sorry...\n\n");
		ret = OMAPCONF_ERR_CPU;
		goto audit_performances_exit;
	}

	/* Retrieve a writable directory */
	workdir = workdir_get();
	if (workdir != NULL) {
		strcpy(irq_snap_file1, workdir);
		strcpy(irq_snap_file2, workdir);
		strcpy(timerstats_file, workdir);
		strcpy(perf_summary_file, workdir);
		strcat(irq_snap_file1, "proc_interrupts_1");
		strcat(irq_snap_file2, "proc_interrupts_2");
		strcat(timerstats_file, "proc_timerstats");
		strcat(perf_summary_file, "performance_audit_report.txt");
		skip_irq_audit = 0;
		skip_timerstats_audit = 0;
	} else {
		skip_irq_audit = 1;
		skip_timerstats_audit = 1;
	}

	/* Open trace output file */
	fp = fopen(perf_summary_file, "w");
	if (fp == NULL) {
		fprintf(stderr, "%s(): could not create %s!\n",
			__func__, perf_summary_file);
	} else {
		fprintf(fp, "OMAP Performance Audit Summary\n\n");
		omapconf_revision_show(fp);
		chips_info_show(fp, 1);
		release_info_show(fp);
	}

	/* Retrieve number of CPU cores and allocate buffers */
	cpu_cores_cnt = cpu_cores_count_get();
	if (cpu_cores_cnt < 1) {
		skip_proc_stats_audit = 1;
	} else {
		dprintf("%s(): found %u cores\n", __func__, cpu_cores_cnt);
		cpu_online = malloc(cpu_cores_cnt * sizeof(unsigned int));
		idle_t0 = malloc(cpu_cores_cnt * sizeof(unsigned int));
		iowait_t0 = malloc(cpu_cores_cnt * sizeof(unsigned int));
		sum_t0 = malloc(cpu_cores_cnt * sizeof(unsigned int));
		idle_t1 = malloc(cpu_cores_cnt * sizeof(unsigned int));
		iowait_t1 = malloc(cpu_cores_cnt * sizeof(unsigned int));
		sum_t1 = malloc(cpu_cores_cnt * sizeof(unsigned int));
		idle_cnt = malloc(cpu_cores_cnt * sizeof(unsigned int));
		iowait_cnt = malloc(cpu_cores_cnt * sizeof(unsigned int));
		sum_cnt = malloc(cpu_cores_cnt * sizeof(unsigned int));
		load = malloc(cpu_cores_cnt * sizeof(double));
		if ((cpu_online == NULL) || (idle_t0 == NULL) ||
			(iowait_t0 == NULL) || (sum_t0 == NULL) ||
			(idle_t1 == NULL) || (iowait_t1 == NULL) ||
			(sum_t1 == NULL) || (iowait_cnt == NULL) ||
			(iowait_cnt == NULL) || (sum_cnt == NULL) ||
			(load == NULL)) {
			fprintf(stderr, "%s(): could not allocate buffers for "
				"CPU stats!\n", __func__);
			skip_proc_stats_audit = 1;
		}
		dprintf("%s(): CPU stats buffers allocated.\n", __func__);
		skip_proc_stats_audit = 0;
	}

	/* Retrieve number of MPU OPPs and allocate buffers */
	opp_cnt = cpufreq_opp_nbr_get();
	if (opp_cnt == 0) {
		skip_cpufreq_audit = 1;
	} else {
		dprintf("%s(): found %u MPU OPPs\n", __func__, opp_cnt);
		time_in_opp_t0 = malloc(opp_cnt * sizeof(uint64_t));
		time_in_opp_t1 = malloc(opp_cnt * sizeof(uint64_t));
		time_in_opp_cnt = malloc(opp_cnt * sizeof(uint64_t));
		if ((time_in_opp_t0 == NULL) || (time_in_opp_t1 == NULL) ||
			(time_in_opp_cnt == NULL)) {
			fprintf(stderr, "%s(): could not allocate buffers for "
				"CPUFREQ stats!\n", __func__);
			skip_cpufreq_audit = 1;
		}
		dprintf("%s(): CPUFREQ stats buffers allocated.\n", __func__);
		skip_cpufreq_audit = 0;
	}

	/* Configure EMIF counters to count data bus busy cycles (OMAP4) */
	if (cpu_is_omap44xx()) {
		ret = emif44xx_perf_cnt_configure(EMIF44XX_0,
			EMIF44XX_PERF_CNT_1,
			EMIF44XX_PERF_CNT_FILTER_DATA_TRANSFER_CYCLES,
			-1, EMIF44XX_MEMADDRSPACE_DISABLED);
		ret |= emif44xx_perf_cnt_configure(EMIF44XX_1,
			EMIF44XX_PERF_CNT_1,
			EMIF44XX_PERF_CNT_FILTER_DATA_TRANSFER_CYCLES,
			-1, EMIF44XX_MEMADDRSPACE_DISABLED);
		if (ret != 0) {
			strncpy(timerstats_summary,
				"Unexpected error occurred while configuring "
				"EMIF performance counters!!!\n\n", 256);
			if (stream != NULL)
				fputs(timerstats_summary, stream);
			if (fp != NULL)
				fputs(timerstats_summary, fp);
			ret = OMAPCONF_ERR_NOT_AVAILABLE;
			goto audit_performances_exit;
		}
		dprintf("%s(): EMIF counters configured.\n", __func__);
	}

	/* Retrieve number of active C-State(s) */
	cstates_nbr = cstate_get_number();
	if (cstates_nbr == 0) {
		cstates_nbr = 0;
		skip_cstate_audit = 1;
	} else {
		skip_cstate_audit = 0;
		dprintf("%s(): found %u C-State(s)\n", __func__, cstates_nbr);
	}

	if (fp != NULL) {
		fprintf(fp, "Audit duration: %us\n", duration);
		fprintf(fp, "Audit initial delay: %us\n\n", delay);
	}
	/* Initial delay before starting capture */
	if (delay >= 1) {
		if (stream != NULL)
			fprintf(stream, "Wait for initial delay (%u sec), then"
				" sample various Key Performance Indicators "
				"over %u second(s) ...\n\n", delay, duration);
		sleep(delay);
	} else {
		if (stream != NULL)
			fprintf(stream,
			"Sampling various Key Performance Indicators "
			"over %u second(s) ...\n\n", duration);
	}

	/* Save current C-State usage & time counters */
	if (skip_cstate_audit == 0) {
		for (i = 0; i < cstates_nbr; i++) {
			cstates_usage[i][0] = cstate_get_usage(i);
			cstates_time[i][0] = cstate_get_time(i);
		}
	}

	/* Save current cpufreq stats */
	if (skip_cpufreq_audit == 0) {
		for (i = 0; i < opp_cnt; i++) {
			time_in_opp_t0[i] = cpufreq_time_in_state_get(i);
			dprintf("%s(): time_in_opp_t0[%u] = %llu\n",
				__func__, i, time_in_opp_t0[i]);
		}
		total_trans_t0 = cpufreq_total_transitions_get();
	}

	/* Save current cpu usage stats */
	if (skip_proc_stats_audit == 0) {
		for (i = 0; i < cpu_cores_cnt; i++) {
			ret = cpu_proc_stats_get(i,
				&idle_t0[i], &iowait_t0[i], &sum_t0[i]);
			if (ret != 0) {
				cpu_online[i] = 0;
				dprintf("%s(): CPU%u offline\n", __func__, i);
			} else {
				cpu_online[i] = 1;
			}

		}
	}

	/* Get current EMIFs total & data transfer cycles */
	if (cpu_is_omap44xx()) {
		emif_busy_cycles[0] = 0;
		for (emif = 0; emif < EMIF44XX_MAX; emif++) {
			emif_busy_cycles[0] += emif44xx_perf_cnt_get_count(
				(emif44xx_ids) emif, EMIF44XX_PERF_CNT_1);
		}
		emif_cycles[0] = emif44xx_perf_cnt_get_time(EMIF44XX_0);
	}

	/* Save current interrupt stats */
	if (skip_irq_audit != 1) {
		ret = irq_snapshot_save(irq_snap_file1);
		if (ret != 0)
			skip_irq_audit = 1;
	}

	/* Save current timer stats */
	/* Stop timer statistic collector, if enabled */
	skip_timerstats_audit = timerstats_stop();
	if (skip_timerstats_audit == 0)
		skip_timerstats_audit = timerstats_start();

	/* Sleep for some time before sampling again usage counters */
	sleep(duration);

	/* Get new EMIFs total & data transfer cycles */
	if (cpu_is_omap44xx()) {
		emif_busy_cycles[1] = 0;
		for (emif = 0; emif < EMIF44XX_MAX; emif++) {
			emif_busy_cycles[1] += emif44xx_perf_cnt_get_count(
				(emif44xx_ids) emif, EMIF44XX_PERF_CNT_1);
		}
		emif_cycles[1] = emif44xx_perf_cnt_get_time(EMIF44XX_0);
	}

	if (skip_timerstats_audit == 0)
		skip_timerstats_audit = timerstats_stop();

	/* Get new interrupts stats */
	if (skip_irq_audit == 0) {
		ret = irq_snapshot_save(irq_snap_file2);
		if (ret != 0) {
			skip_irq_audit = 1;
			remove(irq_snap_file1);
		}
	}

	if (skip_timerstats_audit == 0)
		timerstats_save(timerstats_file);

	/* Get new cpu usage stats*/
	if (skip_proc_stats_audit == 0) {
		for (i = 0; i < cpu_cores_cnt; i++) {
			ret = cpu_proc_stats_get(i,
				&idle_t1[i], &iowait_t1[i], &sum_t1[i]);
			if (ret != 0) {
				cpu_online[i] = 0;
				dprintf("%s(): CPU%u offline\n", __func__, i);
			} else {
				cpu_online[i] = 1;
			}

		}
	}

	/* Get new cpufreq stats */
	if (skip_cpufreq_audit == 0) {
		for (i = 0; i < opp_cnt; i++) {
			time_in_opp_t1[i] = cpufreq_time_in_state_get(i);
			dprintf("%s(): time_in_opp_t1[%u] = %llu\n",
				__func__, i, time_in_opp_t1[i]);
		}
		total_trans_t1 = cpufreq_total_transitions_get();
	}

	/* Get new C-State usage counters */
	if (skip_cstate_audit == 0) {
		for (i = 0; i < cstates_nbr; i++) {
			cstates_usage[i][1] = cstate_get_usage(i);
			cstates_time[i][1] = cstate_get_time(i);
			dprintf("%s(): cstates_usage[%u][0] = "
				"%llu\n", __func__, i, cstates_usage[i][0]);
			dprintf("%s(): cstates_usage[%u][1] = "
				"%llu\n", __func__, i, cstates_usage[i][1]);
			dprintf("%s(): cstates_time[%u][0] = "
				"%llu\n", __func__, i, cstates_time[i][0]);
			dprintf("%s(): cstates_time[%u][1] = "
				"%llu\n", __func__, i, cstates_time[i][1]);
		}
	}

	/* Process data */
	if (cpu_is_omap44xx()) {
		emif_delta_busy_cycles = count32_delta(
			emif_busy_cycles[0], emif_busy_cycles[1]);
		emif_delta_cycles = 2 * count32_delta(
			emif_cycles[0], emif_cycles[1]);
		dprintf("%s(): EMIF delta_busy_cycles=%u, delta_cycles=%u\n",
			__func__, emif_delta_busy_cycles, emif_delta_cycles);
		emif_load = 100.0 * (
			(double) emif_delta_busy_cycles /
				emif_delta_cycles);
		dprintf("%s(): EMIF load = %lf%%\n", __func__, emif_load);
	}

	if (skip_cpufreq_audit == 0) {
		total_trans_cnt = count64_delta(total_trans_t0, total_trans_t1);
		dprintf("CPUFREQ:\n");
		dprintf("  total transitions = %llu\n", total_trans_cnt);
		for (i = 0; i < opp_cnt; i++) {
			time_in_opp_cnt[i] =
				count64_delta(time_in_opp_t0[i],
					time_in_opp_t1[i]);
			#ifdef AUDIT_DEBUG
			/* FIXME: retrieve cpufreq sampling rate (variable) */
			if (cpu_is_omap44xx())
				printf("  time in OPP %s = %llums\n",
					opp44xx_name_get(i + 1, OMAP4_VDD_MPU),
					time_in_opp_cnt[i] * 10);
			else
				printf("  time in OPP %s = %llums\n",
					opp54xx_name_get(i + 1),
					time_in_opp_cnt[i] * 10);
			#endif
		}
	}

	if (skip_cstate_audit == 0) {
		for (i = 0; i < cstates_nbr; i++) {
			cstates_usage[i][2] = count64_delta(
				cstates_usage[i][0], cstates_usage[i][1]);

			cstates_time[i][2] = count64_delta(
				cstates_time[i][0], cstates_time[i][1]);
		}
	}

	/* Compute & Show C-State Statistics */
	if (skip_cstate_audit == 1) {
		strncpy(timerstats_summary,
			"WARNING: could not retrieve C-State number. "
			"Skipping C-States audit.\n\n", 256);
		if (stream != NULL)
			fputs(timerstats_summary, stream);
		if (fp != NULL)
			fputs(timerstats_summary, fp);
	} else {
		autoadjust_table_init(table);
		row = 0;
		strncpy(table[row][0], "C-State", TABLE_MAX_ELT_LEN);
		strncpy(table[row][1], "Entered?", TABLE_MAX_ELT_LEN);
		strncpy(table[row][2], "Hit Number", TABLE_MAX_ELT_LEN);
		strncpy(table[row][3], "Time Spent (s)", TABLE_MAX_ELT_LEN);
		strncpy(table[row][4], "Time Spent (%)", TABLE_MAX_ELT_LEN);
		row++;

		strncpy(table[row][0], "Active + \"C0\"", TABLE_MAX_ELT_LEN);
		strncpy(table[row][1], "Yes", TABLE_MAX_ELT_LEN);
		active_c0_time = duration * 1000000;
		for (i = 0; i < cstates_nbr; i++) {
			if (active_c0_time > cstates_time[i][2])
				active_c0_time -= cstates_time[i][2];
			else
				/*
				 * It may be possible that
				 * active_c0_time is < cstates_time[i][2]
				 * (duration may fluctuate a little depending on
				 * system load). Make sure it doesn't cross 0 as
				 * it's an unsigned interger.
				 */
				active_c0_time = 0;

		}
		sec = active_c0_time / 1000000;
		msec = (active_c0_time % 1000000) / 1000;
		usec = active_c0_time % 1000;
		snprintf(table[row][3], TABLE_MAX_ELT_LEN,
			"%llus %llums %lluus", sec, msec, usec);
		pct = ((double) active_c0_time / (double)
					(duration * 1000000)) * 100.0;
		snprintf(table[row][4], TABLE_MAX_ELT_LEN, "%3.1f%%", pct);
		row++;

		for (i = 0; i < cstates_nbr; i++) {
			snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s",
				cstate_get_name(i, name));
			if (cstates_usage[i][2] != 0) {
				dprintf("%s(): C%u entered\n", __func__, i + 1);
				strncpy(table[row][1], "Yes",
					TABLE_MAX_ELT_LEN);

				snprintf(table[row][2], TABLE_MAX_ELT_LEN,
					"%llu", cstates_usage[i][2]);

				sec = cstates_time[i][2] / 1000000;
				msec = (cstates_time[i][2] % 1000000) / 1000;
				usec = cstates_time[i][2] % 1000;
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"%llus %llums %lluus", sec, msec, usec);

				pct = ((double) cstates_time[i][2] / (double)
					(duration * 1000000)) * 100.0;
				snprintf(table[row][4], TABLE_MAX_ELT_LEN,
					"%3.1f%%", pct);
			} else {
				dprintf("%s(): C%u not entered\n",
					__func__, i + 1);
				strncpy(table[row][1], "No", TABLE_MAX_ELT_LEN);
			}
			row++;
		}

		/* Print results */
		strncpy(timerstats_summary,
			"NB: this table shows statistics about "
			"the ATTEMPTED C-States, not the effectively "
			"entered C-States (not supported by kernel "
			"idle framework yet).\nAs a consequence, these "
			"C-States MAY or MAY NOT have been entered, "
			"depending on HW conditions.\n\n\n", 256);
		if (stream != NULL) {
			autoadjust_table_fprint(stream, table, row, 5);
			fputs(timerstats_summary, stream);
		}
		if (fp != NULL) {
			autoadjust_table_fprint(fp, table, row, 5);
			fputs(timerstats_summary, fp);
		}
	}

	/* Show CPUFreq stats */
	if (skip_cpufreq_audit == 1) {
		strncpy(timerstats_summary, "WARNING: could not retrieve MPU "
			"OPP number. CPUFreq audit skipped.\n\n", 256);
		if (stream != NULL)
			fputs(timerstats_summary, stream);
		if (fp != NULL)
			fputs(timerstats_summary, fp);
	} else {
		autoadjust_table_init(table);
		row = 0;
		strncpy(table[row][0], "MPU OPP", TABLE_MAX_ELT_LEN);
		strncpy(table[row][1], "Time Spent in OPP", TABLE_MAX_ELT_LEN);
		row++;

		for (i = 0; i < opp_cnt; i++) {
			if (cpu_is_omap44xx())
				snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s",
					opp44xx_name_get(i + 1, OMAP4_VDD_MPU));
			else
				snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s",
					opp54xx_name_get(i + 1));
			snprintf(table[row][1], TABLE_MAX_ELT_LEN,
				"%llus%llums",
				time_in_opp_cnt[i] / 100,
				(time_in_opp_cnt[i] % 100) * 10);
			row++;
		}

		cpufreq_scaling_governor_get(name);
		if (name != NULL)
			sprintf(timerstats_summary,
				"CPUFreq Governor: %s\n", name);
		else
			sprintf(timerstats_summary,
				"CPUFreq Governor: not found!\n");
		if (stream != NULL)
			fputs(timerstats_summary, stream);
		if (fp != NULL)
			fputs(timerstats_summary, fp);

		sprintf(timerstats_summary,
			"Total number of OPP transitions: %llu\n\n",
			total_trans_cnt);
		if (stream != NULL) {
			fputs(timerstats_summary, stream);
			autoadjust_table_fprint(stream, table, row, 2);
			fprintf(stream, "\n");
		}
		if (fp != NULL) {
			fputs(timerstats_summary, fp);
			autoadjust_table_fprint(fp, table, row, 2);
			fprintf(fp, "\n");
		}
	}

	/* Show CPU Load stats */
	if (skip_proc_stats_audit == 1) {
		strncpy(timerstats_summary, "WARNING: could not retrieve CPU "
			"cores number. CPU Load audit skipped.\n\n", 256);
		if (stream != NULL)
			fputs(timerstats_summary, stream);
		if (fp != NULL)
			fputs(timerstats_summary, fp);
	} else {
		autoadjust_table_init(table);
		row = 0;
		strncpy(table[row][0], "CPU", TABLE_MAX_ELT_LEN);
		strncpy(table[row][1], "Average Load (*)", TABLE_MAX_ELT_LEN);
		row++;

		cpu_online_cores_cnt = 0;
		load_total = 0.0;
		for (i = 0; i < cpu_cores_cnt; i++) {
			snprintf(table[row][0], TABLE_MAX_ELT_LEN, "CPU%u", i);
			if ((i >= 1) && (cpu_online[i] == 0)) {
				snprintf(table[row][1], TABLE_MAX_ELT_LEN,
					"Offline");
				row++;
				continue;
			}

			idle_cnt[i] =
				count32_delta(idle_t0[i], idle_t1[i]);
			iowait_cnt[i] =
				count32_delta(iowait_t0[i], iowait_t1[i]);
			sum_cnt[i] =
				count32_delta(sum_t0[i], sum_t1[i]);
			dprintf("%s(): idle_cnt[%u] = %u, iowait_cnt[%u] = %u, "
				"sum_cnt[%u] = %u\n", __func__, i, idle_cnt[i],
				i, iowait_cnt[i], i, sum_cnt[i]);
			if (sum_cnt[i] != 0) {
				load[i] = cpu_load_get(idle_cnt[i],
					iowait_cnt[i], sum_cnt[i]);
				cpu_online_cores_cnt++;
			} else {
				/*
				 * Due to tickless feature, it is possible that
				 * that no tick occured during this sampling
				 * window and so /proc/stat counters were not
				 * incremented. => cpu load = 0.
				 */
				load[i] = 0.0;
			}
			load_total += load[i];
			dprintf("%s(): CPU%u load=%.2lf%%\n",
					__func__, i, load[i]);
			snprintf(table[row][1], TABLE_MAX_ELT_LEN, "%.2lf%%",
				load[i]);
			row++;
		}
		dprintf("%s(): cpu_online_cores_cnt=%u\n",
			__func__, cpu_online_cores_cnt);
		load_total = load_total / cpu_online_cores_cnt;
		snprintf(table[row][0], TABLE_MAX_ELT_LEN, "Total");
		snprintf(table[row][1], TABLE_MAX_ELT_LEN, "%.2lf%%",
			load_total);
		row++;

		strncpy(timerstats_summary, "(*) CANNOT be converted to Mhz. "
			"OPP may have changed during the audit.\n\n\n", 256);
		if (stream != NULL) {
			autoadjust_table_fprint(stream, table, row, 2);
			fputs(timerstats_summary, stream);
		}
		if (fp != NULL) {
			autoadjust_table_fprint(fp, table, row, 2);
			fputs(timerstats_summary, fp);
		}
	}

	/* Show EMIF stats */
	if (cpu_is_omap44xx()) {
		autoadjust_table_init(table);
		row = 0;
		strncpy(table[row][0], "EMIF", TABLE_MAX_ELT_LEN);
		strncpy(table[row][1], "Average Load (*)", TABLE_MAX_ELT_LEN);
		row++;
		strncpy(table[row][0], "Total EMIF Data Bus Load",
			TABLE_MAX_ELT_LEN);
		snprintf(table[row][1], TABLE_MAX_ELT_LEN, "%.2lf%%",
				(double) emif_load);
		row++;
		strncpy(timerstats_summary, "(*) CANNOT be converted to memory "
			"bandwidth (MB/s).\n    DDR data busy cycles may be "
			"commands (not data) and data size is unknown.\n\n\n",
			256);
		if (stream != NULL) {
			autoadjust_table_fprint(stream, table, row, 2);
			fputs(timerstats_summary, stream);
		}

		if (fp != NULL) {
			autoadjust_table_fprint(fp, table, row, 2);
			fputs(timerstats_summary, fp);
		}
	}


	/* Show interrupts stats */
	if (skip_irq_audit == 1) {
		strncpy(timerstats_summary,
			"WARNING: could not save a snapshot of "
			"/proc/interrupts file. "
			"IRQ audit skipped.\n\n", 256);
		if (stream != NULL)
			fputs(timerstats_summary, stream);
		if (fp != NULL)
			fputs(timerstats_summary, fp);
	} else {
		fp_irq_1 = fopen(irq_snap_file1, "r");
		fp_irq_2 = fopen(irq_snap_file2, "r");
		if ((fp_irq_1 == NULL) || (fp_irq_2 == NULL)) {
			fprintf(stderr, "%s(): could not open interrupts "
				"snapshot files!\n\n", __func__);
			ret = OMAPCONF_ERR_NOT_AVAILABLE;
			goto audit_performances_exit;
		}

		autoadjust_table_init(table);
		row = 0;
		strncpy(table[row][0], "IRQ #", TABLE_MAX_ELT_LEN);
		strncpy(table[row][1], "Device Name", TABLE_MAX_ELT_LEN);
		strncpy(table[row][2], "Occurrence", TABLE_MAX_ELT_LEN);
		strncpy(table[row][3], "Proportion", TABLE_MAX_ELT_LEN);
		strncpy(table[row][4], "Rate", TABLE_MAX_ELT_LEN);
		row++;

		irq_total_count = irq_total_count_get(fp_irq_2)
			- irq_total_count_get(fp_irq_1);
		dprintf("%s(): irq_total_count=%d\n", __func__,
			irq_total_count);
		occurred_irq_count = irq_occurred_list_get(fp_irq_1, fp_irq_2,
			&occurred_irq_list);
		dprintf("%s(): # of irq lines that occurred = %d\n", __func__,
			occurred_irq_count);
		irq_occurred_list_sort(&occurred_irq_list);
		for (i = 0; i < occurred_irq_count; i++) {
			genlist_get(&occurred_irq_list, i, &irq_inf);
			snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%d",
				irq_inf.nbr);
			strncpy(table[row][1], irq_inf.dev_name,
				TABLE_MAX_ELT_LEN);
			pct = (double) irq_inf.count / (double) irq_total_count;
			pct *= 100.0;
			snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%u",
				irq_inf.count);
			snprintf(table[row][3], TABLE_MAX_ELT_LEN, "%.1lf%%",
				pct);
			pct = (double) irq_inf.count / (double) duration;
			snprintf(table[row][4], TABLE_MAX_ELT_LEN, "%.1lf/sec",
				pct);
			row++;
		}

		genlist_free(&occurred_irq_list);
		fclose(fp_irq_1);
		remove(irq_snap_file1);
		fclose(fp_irq_2);
		remove(irq_snap_file2);

		sprintf(timerstats_summary,
			"CPU was interrupted %d times by the following %d "
			"sources:\n", irq_total_count, occurred_irq_count);
		if (stream != NULL) {
			fputs(timerstats_summary, stream);
			autoadjust_table_fprint(stream, table, row, 5);
		}
		if (fp != NULL) {
			fputs(timerstats_summary, fp);
			autoadjust_table_fprint(fp, table, row, 5);
		}
	}

	/* Show timer stats */
	if (skip_timerstats_audit != 0) {
		strncpy(timerstats_summary,
			"Timer Statistics: unable to capture kernel timer "
			"statistics.\nMake sure that CONFIG_TIMER_STATS "
			"are enabled in the kernel configuration.\n\n", 256);
		if (stream != NULL)
			fputs(timerstats_summary, stream);
		if (fp != NULL)
			fputs(timerstats_summary, fp);
	} else {
		fp_timerstats = fopen(timerstats_file, "r");
		if (fp_timerstats == NULL) {
			fprintf(stderr, "%s(): could not open timer stats "
				"snapshot file!\n\n", __func__);
			ret = OMAPCONF_ERR_NOT_AVAILABLE;
			goto audit_performances_exit;
		}

		autoadjust_table_init(table);
		row = 0;
		strncpy(table[row][0], "# Timer Events", TABLE_MAX_ELT_LEN);
		strncpy(table[row][1], "Deferrable", TABLE_MAX_ELT_LEN);
		strncpy(table[row][2], "Process ID", TABLE_MAX_ELT_LEN);
		strncpy(table[row][3], "Process Name", TABLE_MAX_ELT_LEN);
		strncpy(table[row][4], "Init Function", TABLE_MAX_ELT_LEN);
		strncpy(table[row][5], "Callback Function", TABLE_MAX_ELT_LEN);
		row++;

		timer_count = timerstats_list_get(fp_timerstats,
			&timerstats_list);
		dprintf("%s(): # of timers that occurred = %d\n", __func__,
			timer_count);
		timerstats_list_sort(&timerstats_list);

		for (i = 0; i < timer_count; i++) {
			genlist_get(&timerstats_list, i, &timer_inf);
			snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%d",
				timer_inf.count);
			strncpy(table[row][1], timer_inf.deferrable,
				TABLE_MAX_ELT_LEN);
			snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%d",
				timer_inf.pid);
			strncpy(table[row][3], timer_inf.name,
				TABLE_MAX_ELT_LEN);
			strncpy(table[row][4], timer_inf.init_fxn,
				TABLE_MAX_ELT_LEN);
			strncpy(table[row][5], timer_inf.callback,
				TABLE_MAX_ELT_LEN);
			row++;
		}

		timerstats_get_summary(fp_timerstats, &timerstats_summary[0]);
		genlist_free(&timerstats_list);
		fclose(fp_timerstats);
		remove(timerstats_file);

		if (stream != NULL) {
			fputs(timerstats_summary, stream);
			autoadjust_table_fprint(stream, table, row, 6);
		}
		if (fp != NULL) {
			fputs(timerstats_summary, fp);
			autoadjust_table_fprint(fp, table, row, 6);
		}
	}
	if ((fp != NULL) && (stream != NULL))
		fprintf(stream, "Performance Audit data saved into "
			"\"%s\" file.\n\n", perf_summary_file);

	ret = 0;

audit_performances_exit:
	if (cpu_online != NULL)
		free(cpu_online);
	if (idle_t0 != NULL)
		free(idle_t0);
	if (iowait_t0 != NULL)
		free(iowait_t0);
	if (sum_t0 != NULL)
		free(sum_t0);
	if (idle_t1 != NULL)
		free(idle_t1);
	if (iowait_t1 != NULL)
		free(iowait_t1);
	if (sum_t1 != NULL)
		free(sum_t1);
	if (idle_cnt != NULL)
		free(idle_cnt);
	if (iowait_cnt != NULL)
		free(iowait_cnt);
	if (sum_cnt != NULL)
		free(sum_cnt);
	if (load != NULL)
		free(load);

	if (time_in_opp_t0 != NULL)
		free(time_in_opp_t0);
	if (time_in_opp_t1 != NULL)
		free(time_in_opp_t1);
	if (time_in_opp_cnt != NULL)
		free(time_in_opp_cnt);

	if (fp != NULL)
		fclose(fp);

	return ret;
}
Beispiel #5
0
/* ------------------------------------------------------------------------*//**
 * @FUNCTION		autoadjust_table_print
 * @BRIEF		print to console elements into a table which size
 *			automatically adjusts.
 * @RETURNS		0 in case of success
 *			-1 in case of incorrect pointer
 *			-2 in case of memory allocation error
 *			-3 one element of the table is longer than
 *			TABLE_MAX_ELT_LEN
 * @param[in]		table: elements to be printed
 *			format: table[row][col][string]
 * @param[in]		row_nbr: number of rows
 * @param[in]		col_nbr: number of columns
 * @DESCRIPTION		print to console elements into a table which size
 *			automatically adjusts. The printed table is like this:
 *	|------------------------------------------------------------------|
 *	| elements[0][0]     | elements[0][1]     | elements[0][col-1]     |
 *	|------------------------------------------------------------------|
 *	| elements[1][0]     | elements[1][1]     | elements[1][col-1]     |
 *	| elements[2][0]     | elements[2][1]     | elements[2][col-1]     |
 *	| elements[row-1][0] | elements[row-1][1] | elements[row-1][col-1] |
 *	|------------------------------------------------------------------|
 *//*------------------------------------------------------------------------ */
int autoadjust_table_print(
	char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN],
	unsigned int row_nbr, unsigned int col_nbr)
{
	return autoadjust_table_fprint(stdout, table, row_nbr, col_nbr);
}
Beispiel #6
0
/* ------------------------------------------------------------------------*//**
 * @FUNCTION		opp_show
 * @BRIEF		show current operating voltages and key clock rates.
 * @RETURNS		0 in case of success
 *			OMAPCONF_ERR_REG_ACCESS
 *			OMAPCONF_ERR_CPU
 *			OMAPCONF_ERR_INTERNAL
 * @param[in,out]	stream: output file stream (opened, != NULL)
 * @DESCRIPTION		show current operating voltages and key clock rates.
 *//*------------------------------------------------------------------------ */
int opp_show(FILE *stream)
{
	int volt, volt2;
	const char *opp_s, *opp_s2;
	int temp;
	int rate_mpu, rate_mpu_por;
	int rate_dsp, rate_iva, rate_gpu;
	int rate_dsp_por, rate_iva_por, rate_gpu_por, rate_aess_por;
	int rate_l3, rate_l3_por;
	int rate_l4, rate_emif, rate_lpddr2, rate_aess, rate_iss,
		rate_fdif, rate_dss, rate_bb2d, rate_hsi;
	mod_module_mode mmode;
	int rate_cal, rate_ipu, rate_c2c;
	char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN];
	unsigned int row = 0;
	unsigned int retry_cnt = 0;
	unsigned int found = 0;
	const genlist *voltdm_list;
	int i, vdd_count;
	const char voltdm[VOLTDM_MAX_NAME_LENGTH];
	char prev_gov[CPUFREQ_GOV_MAX_NAME_LENGTH],
		prev_gov2[CPUFREQ_GOV_MAX_NAME_LENGTH];
	const char *temp_sensor;

	/* Switch to userspace governor temporarily,
	 * so that OPP cannot change during audit and does not false it.
	 */
	cpufreq_scaling_governor_set("userspace", prev_gov);

	autoadjust_table_init(table);
	row = 0;
	strncpy(table[row][1], "Temperature", TABLE_MAX_ELT_LEN);
	strncpy(table[row][2], "Voltage", TABLE_MAX_ELT_LEN);
	strncpy(table[row][3], "Frequency", TABLE_MAX_ELT_LEN);
	strncpy(table[row][4], "OPerating Point", TABLE_MAX_ELT_LEN);
	row++;

	/*
	 * In order to make sure all details (OPP, voltage, clock rates) are
	 * coherent (due to potential OPP change in between), must use a loop,
	 * checking that OPP and voltage did not change and that at least ONE
	 * clock rate is aligned to expected rate for the detected OPP.
	 */
	dprintf("%s():\n", __func__);

	voltdm_list = voltdm_list_get();
	if (voltdm_list == NULL)
		return OMAPCONF_ERR_INTERNAL;
	vdd_count = voltdm_count_get();
	if (vdd_count < 0)
		return OMAPCONF_ERR_INTERNAL;
	dprintf("found %d voltage domains\n", vdd_count);
	for (i = 1; i < vdd_count; i++) {
		genlist_get((genlist *) voltdm_list, i, (char *) &voltdm);
		snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s / VDD_CORE%u",
				voltdm, i);
		dprintf("  %s:\n", voltdm);

		/* Retrieve OPP and clock rates */
		retry_cnt = 0;
		found = 0;
		do {
			dprintf("    TRY #%u:\n", retry_cnt);
			if (retry_cnt == 0)
				/* Print warning on first try */
				opp_s = opp_get(voltdm, 0);
			else
				opp_s = opp_get(voltdm, 1);
			if (opp_s == NULL) {
				dprintf("      OPP NOT detected!\n");
				opp_s = OPP_UNKNOWN;
			} else {
				dprintf("      OPP detected: %s\n", opp_s);
			}

			volt = voltdm_voltage_get(voltdm);
			dprintf("      Voltage: %duV\n", volt);

			if (strcmp(voltdm, "VDD_MPU") == 0) {
				rate_mpu = mod_clk_rate_get("MPU");
				if (strcmp(opp_s, OPP_UNKNOWN) != 0)
					rate_mpu_por = mod_por_clk_rate_get(
						"MPU", opp_s);
				else
					rate_mpu_por = -1;
				dprintf(
					"      MPU Rate: %dKHz, POR Rate: %dKHz\n",
					rate_mpu, rate_mpu_por);
			} else if ((strcmp(voltdm, "VDD_IVA") == 0) ||
				(strcmp(voltdm, "VDD_MM") == 0)) {
				rate_dsp_por = -1;
				rate_iva_por = -1;
				rate_aess_por = -1;
				rate_gpu_por = -1;
				rate_dsp = mod_clk_rate_get("DSP");
				rate_iva = mod_clk_rate_get("IVA");
				if (cpu_is_omap44xx())
					rate_aess = mod_clk_rate_get("AESS");
				else if (cpu_is_omap54xx())
					rate_gpu = mod_clk_rate_get("GPU");

				if (strcmp(opp_s, OPP_UNKNOWN) != 0) {
					rate_dsp_por = mod_por_clk_rate_get(
						"DSP", opp_s);
					rate_iva_por = mod_por_clk_rate_get(
						"IVA", opp_s);
					if (cpu_is_omap44xx())
						rate_aess_por =
							mod_por_clk_rate_get(
								"AESS", opp_s);
					else if (cpu_is_omap54xx())
						rate_gpu_por =
							mod_por_clk_rate_get(
								"GPU", opp_s);
				}
				dprintf(
					"      DSP Rate: %dMHz, POR Rate: %dMHz\n",
					rate_dsp, rate_dsp_por);
				dprintf(
					"      IVA Rate: %dMHz, POR Rate: %dMHz\n",
					rate_iva, rate_iva_por);
				if (cpu_is_omap44xx()) {
					dprintf(
						"      AESS Rate: %dMHz, POR Rate: %dMHz\n",
						rate_aess, rate_aess_por);
				} else if (cpu_is_omap54xx()) {
					dprintf(
						"      GPU Rate: %dMHz, POR Rate: %dMHz\n",
						rate_gpu, rate_gpu_por);
				}
			} else if (strcmp(voltdm, "VDD_CORE") == 0) {
				rate_l3 = mod_clk_rate_get("L3");
				if (strcmp(opp_s, OPP_UNKNOWN) != 0)
					rate_l3_por = mod_por_clk_rate_get(
						"L3", opp_s);
				else
					rate_l3_por = -1;
				dprintf(
					"      L3_1 Rate: %dMHz, POR Rate: %dMHz\n",
					rate_l3, rate_l3_por);

				rate_emif = mod_clk_rate_get("EMIF");
				rate_lpddr2 = mod_clk_rate_get("MEM");
				rate_l4 = mod_clk_rate_get("L4");
				if (cpu_is_omap44xx())
					rate_gpu = mod_clk_rate_get("GPU");
				else if (cpu_is_omap54xx())
					rate_aess = mod_clk_rate_get("AESS");
				rate_iss = mod_clk_rate_get("ISS");
				rate_fdif = mod_clk_rate_get("FDIF");
				if (!cpu_is_omap44xx())
					rate_cal = mod_clk_rate_get("CAL");
				else
					rate_cal = -1;
				rate_ipu = mod_clk_rate_get("IPU");
				rate_dss = mod_clk_rate_get("DSS");
				rate_hsi = mod_clk_rate_get("HSI");
				if (cpu_is_omap4470() || cpu_is_omap54xx())
					rate_bb2d = mod_clk_rate_get("BB2D");
				else
					rate_bb2d = -1;
				rate_c2c = mod_clk_rate_get("C2C");
			}


			if (strcmp(opp_s, OPP_UNKNOWN) == 0) {
				dprintf(
					"      Could not detect OPP, aborting for this domain.\n");
				break;
			}

			opp_s2 = opp_get(voltdm, 1);
			if (opp_s2 == NULL) {
				dprintf("      OPP NOT detected! (2)\n");
				opp_s2 = OPP_UNKNOWN;
			} else {
				dprintf("      OPP detected: %s (2)\n", opp_s2);
			}

			volt2 = voltdm_voltage_get(voltdm);
			dprintf("      Voltage (2): %dV\n", volt2);

			if (strcmp(voltdm, "VDD_MPU") == 0) {
				found = ((rate_mpu == rate_mpu_por) &&
					(strcmp(opp_s, opp_s2) == 0) &&
					(volt == volt2));
			} else if (strcmp(voltdm, "VDD_IVA") == 0) {
				found = ((strcmp(opp_s, opp_s2) == 0) &&
					(volt == volt2) &&
					(((unsigned int) rate_dsp == (unsigned int) rate_dsp_por) ||
						((unsigned int) rate_iva == (unsigned int) rate_iva_por) ||
						((unsigned int) rate_aess == (unsigned int) rate_aess_por)));
			} else if (strcmp(voltdm, "VDD_MM") == 0) {
				found = ((strcmp(opp_s, opp_s2) == 0) &&
					(volt == volt2) &&
					((rate_dsp == rate_dsp_por) ||
						(rate_iva == rate_iva_por) ||
						(rate_gpu == rate_gpu_por)));
			} else if (strcmp(voltdm, "VDD_CORE") == 0) {
				found = ((strcmp(opp_s, opp_s2) == 0) &&
					(volt == volt2) &&
					(rate_l3 == rate_l3_por));
			}
			dprintf("      found=%u\n", found);

			retry_cnt++;
		} while ((retry_cnt < OPP_MAX_RETRY) && (found == 0));

		/* Print temperature */
		temp_sensor = temp_sensor_voltdm2sensor(voltdm);
		if (temp_sensor == NULL) {
			snprintf(table[row][1], TABLE_MAX_ELT_LEN, "NA");
		} else {
			temp = temp_sensor_get(temp_sensor);
			if (temp != TEMP_ABSOLUTE_ZERO)
				snprintf(table[row][1], TABLE_MAX_ELT_LEN,
					"%dC / %dF", temp,
					celcius2fahrenheit(temp));
			else
				snprintf(table[row][1], TABLE_MAX_ELT_LEN,
					"NA");
		}

		/* Print voltage */
		if (volt < 0)
			snprintf(table[row][2], TABLE_MAX_ELT_LEN, "NA");
		else if (!cpu_is_omap44xx())
			snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%.3lf V",
				uv2v(volt));
		else
			snprintf(table[row][2], TABLE_MAX_ELT_LEN, "%.6lf V",
				uv2v(volt));

		/* Print OPP */
		if (retry_cnt < OPP_MAX_RETRY) {
			strncpy(table[row][4], opp_s,
				TABLE_MAX_ELT_LEN);
		} else {
			fprintf(stderr,
				"omapconf: too many %s OPP changes, could not retrieve it!!!\n",
				voltdm);
			strncpy(table[row][4], "ERROR", TABLE_MAX_ELT_LEN);
		}
		row++;

		/* Print clock rates */
		if (strcmp(voltdm, "VDD_MPU") == 0) {
			if (cpu_is_online(1) == 1)
				strncpy(table[row][0], "  MPU (CPU1 ON)",
					TABLE_MAX_ELT_LEN);
			else
				strncpy(table[row][0], "  MPU (CPU1 OFF)",
					TABLE_MAX_ELT_LEN);
			snprintf(table[row][3], TABLE_MAX_ELT_LEN, " %-4d MHz",
				rate_mpu / 1000);
			row += 2;
		} else if ((strcmp(voltdm, "VDD_IVA") == 0) ||
			(strcmp(voltdm, "VDD_MM") == 0)) {
			strncpy(table[row][0], "  IVA", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("IVA");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_iva / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_iva / 1000);
			row++;

			if (cpu_is_omap44xx()) {
				strncpy(table[row][0], "  AESS",
					TABLE_MAX_ELT_LEN);
				mmode = mod_mode_get("AESS");
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_aess / 1000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						" %-4d MHz", rate_aess / 1000);
				row++;
			} else if (cpu_is_omap54xx()) {
				strncpy(table[row][0], "  GPU",
					TABLE_MAX_ELT_LEN);
				mmode = mod_mode_get("GPU");
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_gpu / 1000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						" %-4d MHz", rate_gpu / 1000);
				row++;
			}

			strncpy(table[row][0], "  DSP", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("DSP");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_dsp / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_dsp / 1000);
			row += 2;
		} else if (strcmp(voltdm, "VDD_CORE") == 0) {
			strncpy(table[row][0], "  L3", TABLE_MAX_ELT_LEN);
			snprintf(table[row][3], TABLE_MAX_ELT_LEN, " %-4d MHz",
				rate_l3 / 1000);
			row++;

			strncpy(table[row][0], "  DMM/EMIF", TABLE_MAX_ELT_LEN);
			snprintf(table[row][3], TABLE_MAX_ELT_LEN, " %-4d MHz",
				rate_emif / 1000);
			row++;

			strncpy(table[row][0], "    LP-DDR2",
				TABLE_MAX_ELT_LEN);
			snprintf(table[row][3], TABLE_MAX_ELT_LEN, " %-4d MHz",
				rate_lpddr2 / 1000);
			row++;

			strncpy(table[row][0], "  L4", TABLE_MAX_ELT_LEN);
			snprintf(table[row][3], TABLE_MAX_ELT_LEN, " %-4d MHz",
				rate_l4 / 1000);
			row++;

			if (cpu_is_omap44xx()) {
				strncpy(table[row][0], "  GPU",
					TABLE_MAX_ELT_LEN);
				mmode = mod_mode_get("GPU");
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_gpu / 1000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						" %-4d MHz", rate_gpu / 1000);
				row++;
			} else if (cpu_is_omap54xx()) {
				strncpy(table[row][0], "  AESS",
					TABLE_MAX_ELT_LEN);
				mmode = mod_mode_get("AESS");
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_aess / 1000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						" %-4d MHz", rate_aess / 1000);
				row++;
			}

			strncpy(table[row][0], "  FDIF", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("FDIF");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_fdif / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_fdif / 1000);
			row++;

			if (cpu_is_omap54xx()) {
				strncpy(table[row][0], "  CAL",
					TABLE_MAX_ELT_LEN);
				mmode = mod_mode_get("CAL");
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_cal / 1000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						" %-4d MHz",
						rate_cal / 1000);
				row++;
			}

			strncpy(table[row][0], "  IPU", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("IPU");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_ipu / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_ipu / 1000);
			row++;
			if (cpu_is_omap44xx()) {
				strncpy(table[row][0], "    Cortex-M3 Cores",
					TABLE_MAX_ELT_LEN);
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_ipu / 2000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						" %-4d MHz", rate_ipu / 2000);
				row++;
			} else if (cpu_is_omap54xx()) {
				strncpy(table[row][0], "    Cortex-M4 Cores",
					TABLE_MAX_ELT_LEN);
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_ipu / 2000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						" %-4d MHz", rate_ipu / 2000);
				row++;
			}

			strncpy(table[row][0], "  ISS", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("ISS");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_iss / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_iss / 1000);
			row++;

			strncpy(table[row][0], "  DSS", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("DSS");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_dss / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_dss / 1000);
			row++;

			if (cpu_is_omap4470() || cpu_is_omap54xx()) {
				strncpy(table[row][0], "  BB2D",
					TABLE_MAX_ELT_LEN);
				mmode = mod_mode_get("BB2D");
				if (mmode == MOD_DISABLED_MODE)
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN,
						"(%-4d MHz) (1)",
						rate_bb2d / 1000);
				else
					snprintf(table[row][3],
						TABLE_MAX_ELT_LEN, " %-4d MHz",
						rate_bb2d / 1000);
				row++;
			}

			strncpy(table[row][0], "  HSI", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("HSI");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_hsi / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_hsi / 1000);
			row++;

			strncpy(table[row][0], "  C2C", TABLE_MAX_ELT_LEN);
			mmode = mod_mode_get("C2C");
			if (mmode == MOD_DISABLED_MODE)
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					"(%-4d MHz) (1)", rate_c2c / 1000);
			else
				snprintf(table[row][3], TABLE_MAX_ELT_LEN,
					" %-4d MHz", rate_c2c / 1000);
			row++;
		}
	}

	/* Display table */
	autoadjust_table_fprint(stream, table, row, 5);

	fprintf(stream, "Notes:\n");
	fprintf(stream,
		"  (1) Module is disabled, rate may not be relevant.\n\n");

	/* Restore CPUFreq governor */
	cpufreq_scaling_governor_set(prev_gov, prev_gov2);

	return 0;
}
Beispiel #7
0
/* ------------------------------------------------------------------------*//**
 * @FUNCTION		sr54xx_dump
 * @BRIEF		dump selected registers and pretty-print it in selected
 *			output stream
 * @RETURNS		0 in case of success
 *			OMAPCONF_ERR_CPU
 *			OMAPCONF_ERR_ARG
 * @param[in,out]	stream: output stream
 * @param[in]		id: SR module ID - If id == SR54XX_MODS_COUNT,
 *			dump all SR registers.
 * @DESCRIPTION		dump selected registers and pretty-print it in selected
 *			output stream
 *//*------------------------------------------------------------------------ */
int sr54xx_dump(FILE *stream, sr54xx_mod_id id)
{
	unsigned int i = 0, mid;
	unsigned int val = 0;
	int err = 0;
	reg **mod;
	reg *r;
	char s[TABLE_MAX_ELT_LEN];
	char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN];
	unsigned int row;


	if (stream == NULL) {
		fprintf(stderr, "%s(): stream == NULL!!!\n", __func__);
		err = OMAPCONF_ERR_ARG;
		goto sr54xx_dump_end;
	}

	if (id > SR54XX_MODS_COUNT) {
		fprintf(stderr, "%s(): id (%u) > SR54XX_MODS_COUNT!!! (%u)\n",
			__func__, id, SR54XX_MODS_COUNT);
		err = OMAPCONF_ERR_ARG;
		goto sr54xx_dump_end;
	}

	autoadjust_table_init(table);
	row = 0;

	if (id != SR54XX_MODS_COUNT)
		snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s Reg. Name",
			sr54xx_mod_name_get(id));
	else
		strncpy(table[row][0], "SR Reg. Name", TABLE_MAX_ELT_LEN);
	strncpy(table[row][1], "Reg. Address",
		TABLE_MAX_ELT_LEN);
	strncpy(table[row][2], "Reg. Value", TABLE_MAX_ELT_LEN);
	row++;

	for (mid = SR54XX_SMARTREFLEX_MPU; mid < SR54XX_MODS_COUNT; mid++) {
		if ((id != SR54XX_MODS_COUNT) && (mid != id))
			continue;
		else {
			if (!sr54xx_is_enabled(mid)) {
				if (stream != NULL)
					fprintf(stream, "%s module not running"
						", registers not accessible.\n",
						sr54xx_mod_name_get(mid));
				return 0;
			}

			mod = sr54xx_mods[mid];
			for (i = 0; mod[i] != NULL; i++) {
				r = mod[i];
				/* Read register */
				val = reg_read(r);
				/* Show register name, addr & content */
				snprintf(s, TABLE_MAX_ELT_LEN, "%s", r->name);
				autoadjust_table_strncpy(table, row, 0, s);

				snprintf(s, TABLE_MAX_ELT_LEN, "0x%08X",
					r->addr);
				autoadjust_table_strncpy(table, row, 1, s);

				snprintf(s, TABLE_MAX_ELT_LEN, "0x%08X", val);
				autoadjust_table_strncpy(table, row++, 2, s);
			}
		}
	}

	autoadjust_table_fprint(stream, table, row, 3);

sr54xx_dump_end:
	return err;
}
Beispiel #8
0
/* ------------------------------------------------------------------------*//**
 * @FUNCTION		ctrlmod54xx_io_audit
 * @BRIEF		OMAP5 PADCONF/IO audit.
 * @RETURNS		0 in case of success
 *			OMAPCONF_ERR_ARG
 *			OMAPCONF_ERR_CPU
 * @param[in,out]	stream: output file - NULL: no output (silent)
 * @param[in,out]	err_nbr: pointer to return audit error number
 * @param[in,out]	wng_nbr: pointer to return audit warning number
 * @DESCRIPTION		OMAP5 PADCONF/IO audit.
 *//*------------------------------------------------------------------------ */
int ctrlmod54xx_io_audit(FILE *stream, unsigned int *err_nbr,
	unsigned int *wng_nbr)
{
	const char pass[5] = "pass";
	const char fail[5] = "FAIL";
	const char ignore[5] = "ign.";
	const char warning[5] = "warn";
	char *status;
	char table[TABLE_MAX_ROW][TABLE_MAX_COL][TABLE_MAX_ELT_LEN];
	unsigned int row, i, j, curr, expected, max;
	ctrlmod54xx_golden_item *golden_values;
	reg **ctrlmod_regs;

	CHECK_CPU(54xx, OMAPCONF_ERR_CPU);
	CHECK_NULL_ARG(err_nbr, OMAPCONF_ERR_ARG);
	CHECK_NULL_ARG(wng_nbr, OMAPCONF_ERR_ARG);

	*err_nbr = 0;
	*wng_nbr = 0;

	if (cpu_revision_get() != REV_ES1_0) {
		fprintf(stream,
			"No golden settings available for OMAP5430 ES2.x, sorry...\n\n");
		status = (char *) warning;
		(*wng_nbr)++;
		return OMAPCONF_ERR_CPU;
	}

	for (j = 0; j < 4; j++) {
		autoadjust_table_init(table);
		row = 0;
		switch (j) {
		case 0:
			snprintf(table[row][0], TABLE_MAX_ELT_LEN,
				"CONTROL MODULE CORE registers AUDIT");
			if (cpu_revision_get() == REV_ES1_0) {
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_core54xxes1_golden_values;
				ctrlmod_regs = omap5430es1_ctrl_module_core_mod;
				max = OMAP5430ES1_CTRL_MODULE_CORE_MOD_REGCOUNT;
			} else { /* FIXME WHEN ES2.0 targets available */
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_core54xxes1_golden_values;
				ctrlmod_regs = omap5430_ctrl_module_core_mod;
				max = OMAP5430_CTRL_MODULE_CORE_MOD_REGCOUNT;
			}
			break;
		case 1:
			snprintf(table[row][0], TABLE_MAX_ELT_LEN,
				"CONTROL MODULE CORE PADCONF Registers AUDIT");
			if (cpu_revision_get() == REV_ES1_0) {
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_core_pad54xxes1_golden_values;
				ctrlmod_regs =
					omap5430es1_ctrl_module_core_pad_mod;
				max = OMAP5430_CTRL_MODULE_CORE_PAD_MOD_REGCOUNT;
			} else {
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_core_pad54xxes1_golden_values;
				ctrlmod_regs =
					omap5430_ctrl_module_core_pad_mod;
				max = OMAP5430_CTRL_MODULE_CORE_PAD_MOD_REGCOUNT;
			}
			break;
		case 2:
			snprintf(table[row][0], TABLE_MAX_ELT_LEN,
				"CONTROL MODULE WKUP Registers AUDIT");
			if (cpu_revision_get() == REV_ES1_0) {
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_wkup54xxes1_golden_values;
				ctrlmod_regs = omap5430es1_ctrl_module_wkup_mod;
				max = OMAP5430ES1_CTRL_MODULE_WKUP_MOD_REGCOUNT;
			} else { /* FIXME WHEN ES2.0 targets available */
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_wkup54xxes1_golden_values;
				ctrlmod_regs = omap5430_ctrl_module_wkup_mod;
				max = OMAP5430ES1_CTRL_MODULE_WKUP_MOD_REGCOUNT;
			}
			break;
		case 3:
			snprintf(table[row][0], TABLE_MAX_ELT_LEN,
				"CONTROL MODULE WKUP PADCONF Registers AUDIT");
			if (cpu_revision_get() == REV_ES1_0) {
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_wkup_pad54xxes1_golden_values;
				ctrlmod_regs = omap5430_ctrl_module_wkup_pad_mod;
				max = OMAP5430_CTRL_MODULE_WKUP_PAD_MOD_REGCOUNT;
			} else { /* FIXME WHEN ES2.0 targets available */
				golden_values = (ctrlmod54xx_golden_item *)
					ctrlmod_wkup_pad54xxes1_golden_values;
				ctrlmod_regs = omap5430_ctrl_module_wkup_pad_mod;
				max = OMAP5430_CTRL_MODULE_WKUP_PAD_MOD_REGCOUNT;
			}
			break;

		}
		snprintf(table[row][1], TABLE_MAX_ELT_LEN, "Current");
		snprintf(table[row][2], TABLE_MAX_ELT_LEN, "Expected");
		snprintf(table[row++][3], TABLE_MAX_ELT_LEN, "STATUS");

		for (i = 0; i < max; i++) {
			/* Read register */
			curr = reg_read(ctrlmod_regs[i]);

			/* Store name & register read content in table */
			snprintf(table[row][0], TABLE_MAX_ELT_LEN, "%s",
				(ctrlmod_regs[i])->name);
			snprintf(table[row][1], TABLE_MAX_ELT_LEN, "0x%08X",
				curr);

			/* Compare to golden value */
			switch (golden_values[i].valid) {
			case DATA_INVALID:
			case DATA_TBD:
				status = (char *) warning;
				(*wng_nbr)++;
				snprintf(table[row][2], TABLE_MAX_ELT_LEN,
					"   TBD");
				break;

			case DATA_VALID:
				expected = golden_values[i].golden_value;
				snprintf(table[row][2], TABLE_MAX_ELT_LEN,
					"0x%08X", expected);
				if (curr != expected) {
					status = (char *) fail;
					(*err_nbr)++;
				} else {
					status = (char *) pass;
				}
				break;

			case DATA_IGNORE:
				status = (char *) ignore;
				break;

			default:
				fprintf(stderr,
					"%s(): something's wrong here?! (j=%u, "
					"i=%u, golden_values[i].valid=%u)\n",
					__func__, j, i,	golden_values[i].valid);
			}
			/* Store status in table */
			snprintf(table[row++][3], TABLE_MAX_ELT_LEN, "%s",
				status);
		}

		if (stream != NULL) {
			autoadjust_table_fprint(stream, table, row, 4);
			fprintf(stream, " ### WARNING: PRELIMINARY ###\n");
			fprintf(stream, " ### GOLDEN VALUES STILL TO BE "
				"VERIFIED/COMPLETED!!! ###\n\n");
		}
	}

	/* Print audit results summary */
	if (stream != NULL) {
		if (*err_nbr == 0)
			fprintf(stream, "\nSUCCESS! Clock Speed audit "
				"completed with 0 error (%d warning(s))\n\n",
				*wng_nbr);
		else
			fprintf(stream, "\nFAILED! Clock Speed audit "
				"completed with %d error and %d warning.\n\n",
				*err_nbr, *wng_nbr);
	}

	return 0;
}