void __init tegra_soc_init_dvfs(void)
{
	int i;
	struct clk *c;
	struct dvfs *d;
	int process_id;
	int ret;
	int cpu_process_id = tegra_cpu_process_id();
	int core_process_id = tegra_core_process_id();
	int speedo_id = tegra_soc_speedo_id();

	BUG_ON(speedo_id >= ARRAY_SIZE(cpu_speedo_nominal_millivolts));
	tegra2_dvfs_rail_vdd_cpu.nominal_millivolts =
		cpu_speedo_nominal_millivolts[speedo_id];
	BUG_ON(speedo_id >= ARRAY_SIZE(core_speedo_nominal_millivolts));
	tegra2_dvfs_rail_vdd_core.nominal_millivolts =
		core_speedo_nominal_millivolts[speedo_id];
	tegra2_dvfs_rail_vdd_aon.nominal_millivolts =
		core_speedo_nominal_millivolts[speedo_id];

	tegra_dvfs_init_rails(tegra2_dvfs_rails, ARRAY_SIZE(tegra2_dvfs_rails));
	tegra_dvfs_add_relationships(tegra2_dvfs_relationships,
		ARRAY_SIZE(tegra2_dvfs_relationships));
	/*
	 * VDD_CORE must always be at least 50 mV higher than VDD_CPU
	 * Fill out cpu_core_millivolts based on cpu_millivolts
	 */
	for (i = 0; i < ARRAY_SIZE(dvfs_init); i++) {
		d = &dvfs_init[i];

		process_id = strcmp(d->clk_name, "cpu") ?
			core_process_id : cpu_process_id;
		if ((d->process_id != -1 && d->process_id != process_id) ||
		    (d->speedo_id != -1 && d->speedo_id != speedo_id)) {
			pr_debug("tegra_dvfs: rejected %s speedo %d,"
				" process %d\n", d->clk_name, d->speedo_id,
				d->process_id);
			continue;
		}

		c = tegra_get_clock_by_name(d->clk_name);

		if (!c) {
			pr_debug("tegra_dvfs: no clock found for %s\n",
				d->clk_name);
			continue;
		}

		ret = tegra_enable_dvfs_on_clk(c, d);
		if (ret)
			pr_err("tegra_dvfs: failed to enable dvfs on %s\n",
				c->name);
	}

	if (tegra_dvfs_core_disabled)
		tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_core);

	if (tegra_dvfs_cpu_disabled)
		tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_cpu);
}
Exemple #2
0
void __init tegra2_init_dvfs(void)
{
	int i;
	int speedo_id = tegra_speedo_id();

	if (speedo_id > NUM_SPEED_LEVELS) {
		pr_err("Warning: Unsupported DVFS speed level: %d\n", speedo_id);
		return;
	}

	if (tegra_cpu_process_id > NUM_PROCESS_CORNERS) {
		pr_err("Warning: Unsupported DVFS cpu process id: %d\n",
			tegra_cpu_process_id);
		return;
	}

	if (tegra_core_process_id > NUM_PROCESS_CORNERS) {
		pr_err("Warning: Unsupported DVFS core process id: %d\n",
			tegra_core_process_id);
		return;
	}

	tegra2_dvfs_rail_vdd_cpu.nominal_millivolts =
		cpu_speedo_max_millivolts[speedo_id];
	tegra2_dvfs_rail_vdd_cpu.max_millivolts =
		cpu_speedo_max_millivolts[speedo_id];
	tegra2_dvfs_rail_vdd_core.nominal_millivolts =
		core_speedo_max_millivolts[speedo_id];
	tegra2_dvfs_rail_vdd_core.max_millivolts =
		core_speedo_max_millivolts[speedo_id];
	tegra2_dvfs_rail_vdd_aon.nominal_millivolts =
		core_speedo_max_millivolts[speedo_id];
	tegra2_dvfs_rail_vdd_aon.max_millivolts =
		core_speedo_max_millivolts[speedo_id];

	tegra_dvfs_init_rails(tegra2_dvfs_rails, ARRAY_SIZE(tegra2_dvfs_rails));
	tegra_dvfs_add_relationships(tegra2_dvfs_relationships,
		ARRAY_SIZE(tegra2_dvfs_relationships));
	/*
	 * VDD_CORE must always be at least 50 mV higher than VDD_CPU
	 * Fill out cpu_core_millivolts based on cpu_millivolts
	 */

	dvfs_init_one(&dvfs_cpu[speedo_id][tegra_cpu_process_id]);

	for (i = 0; i < ARRAY_SIZE(dvfs_init); i++)
		dvfs_init_one(&dvfs_init[i]);

	for (i = 0; i < ARRAY_SIZE(dvfs_core); i++)
		dvfs_init_one(&dvfs_core[i][tegra_core_process_id]);

	if (tegra_dvfs_core_disabled)
		tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_core);

	if (tegra_dvfs_cpu_disabled)
		tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_cpu);

	register_reboot_notifier(&tegra_dvfs_reboot_nb);
}
void __init tegra2_init_dvfs(void)
{
	int i;
	struct clk *c;
	struct dvfs *d;
	int ret;
	int cpu_process_id = tegra_cpu_process_id();

	tegra_dvfs_init_rails(tegra2_dvfs_rails, ARRAY_SIZE(tegra2_dvfs_rails));
	tegra_dvfs_add_relationships(tegra2_dvfs_relationships,
		ARRAY_SIZE(tegra2_dvfs_relationships));
	/*
	 * VDD_CORE must always be at least 50 mV higher than VDD_CPU
	 * Fill out cpu_core_millivolts based on cpu_millivolts
	 */
	for (i = 0; i < ARRAY_SIZE(dvfs_init); i++) {
		d = &dvfs_init[i];

		if (d->cpu_process_id != -1 &&
				d->cpu_process_id != cpu_process_id)
			continue;

		c = tegra_get_clock_by_name(d->clk_name);

		if (!c) {
			pr_debug("tegra_dvfs: no clock found for %s\n",
				d->clk_name);
			continue;
		}

		ret = tegra_enable_dvfs_on_clk(c, d);
		if (ret)
			pr_err("tegra_dvfs: failed to enable dvfs on %s\n",
				c->name);
	}

	if (tegra_dvfs_core_disabled)
		tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_core);

	if (tegra_dvfs_cpu_disabled)
		tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_cpu);
}
void __init tegra_soc_init_dvfs(void)
{
	int cpu_speedo_id = tegra_cpu_speedo_id();
	int soc_speedo_id = tegra_soc_speedo_id();
	int cpu_process_id = tegra_cpu_process_id();
#ifdef CONFIG_TEGRA3_LP_CORE_OVERDRIVE
	int core_process_id = 2;
#else
	int core_process_id = tegra_core_process_id();
#endif

	int i;
	int core_nominal_mv_index;
	int cpu_nominal_mv_index;

#ifndef CONFIG_TEGRA_CORE_DVFS
	tegra_dvfs_core_disabled = true;
#endif
#ifndef CONFIG_TEGRA_CPU_DVFS
	tegra_dvfs_cpu_disabled = true;
#endif

	/*
	 * Find nominal voltages for core (1st) and cpu rails before rail
	 * init. Nominal voltage index in the scaling ladder will also be
	 * used to determine max dvfs frequency for the respective domains.
	 */
	core_nominal_mv_index = get_core_nominal_mv_index(soc_speedo_id);
	if (core_nominal_mv_index < 0) {
		tegra3_dvfs_rail_vdd_core.disabled = true;
		tegra_dvfs_core_disabled = true;
		core_nominal_mv_index = 0;
	}
	tegra3_dvfs_rail_vdd_core.nominal_millivolts =
		core_millivolts[core_nominal_mv_index];

	cpu_nominal_mv_index = get_cpu_nominal_mv_index(
		cpu_speedo_id, cpu_process_id, &cpu_dvfs);
	BUG_ON((cpu_nominal_mv_index < 0) || (!cpu_dvfs));
	tegra3_dvfs_rail_vdd_cpu.nominal_millivolts =
		cpu_millivolts[cpu_nominal_mv_index];

	/* Init rail structures and dependencies */
	tegra_dvfs_init_rails(tegra3_dvfs_rails, ARRAY_SIZE(tegra3_dvfs_rails));
	tegra_dvfs_add_relationships(tegra3_dvfs_relationships,
		ARRAY_SIZE(tegra3_dvfs_relationships));

	/* Search core dvfs table for speedo/process matching entries and
	   initialize dvfs-ed clocks */
	for (i = 0; i <  ARRAY_SIZE(core_dvfs_table); i++) {
		struct dvfs *d = &core_dvfs_table[i];
		if (!match_dvfs_one(d, soc_speedo_id, core_process_id))
			continue;
		init_dvfs_one(d, core_nominal_mv_index);
	}

	/* Initialize matching cpu dvfs entry already found when nominal
	   voltage was determined */
	init_dvfs_one(cpu_dvfs, cpu_nominal_mv_index);
	init_dvfs_cold(cpu_dvfs, cpu_nominal_mv_index);

	/* Finally disable dvfs on rails if necessary */
	if (tegra_dvfs_core_disabled)
		tegra_dvfs_rail_disable(&tegra3_dvfs_rail_vdd_core);
	if (tegra_dvfs_cpu_disabled)
		tegra_dvfs_rail_disable(&tegra3_dvfs_rail_vdd_cpu);

	pr_info("tegra dvfs: VDD_CPU nominal %dmV, scaling %s\n",
		tegra3_dvfs_rail_vdd_cpu.nominal_millivolts,
		tegra_dvfs_cpu_disabled ? "disabled" : "enabled");
	pr_info("tegra dvfs: VDD_CORE nominal %dmV, scaling %s\n",
		tegra3_dvfs_rail_vdd_core.nominal_millivolts,
		tegra_dvfs_core_disabled ? "disabled" : "enabled");
}