Example #1
0
static int nvhost_scale_make_freq_table(struct nvhost_device_profile *profile)
{
	unsigned long *freqs;
	int num_freqs, err;
	unsigned long max_freq =  clk_round_rate(profile->clk, UINT_MAX);
	unsigned long min_freq =  clk_round_rate(profile->clk, 0);

	err = tegra_dvfs_get_freqs(clk_get_parent(profile->clk),
				   &freqs, &num_freqs);
	if (err)
		return -ENOSYS;

	/* check for duplicate frequencies at higher end */
	while ((num_freqs >= 2 &&
		freqs[num_freqs - 2] == freqs[num_freqs - 1]) ||
	       (num_freqs && max_freq < freqs[num_freqs - 1]))
		num_freqs--;

	/* check low end */
	while ((num_freqs >= 2 && freqs[0] == freqs[1]) ||
	       (num_freqs && freqs[0] < min_freq)) {
		freqs++;
		num_freqs--;
	}

	if (!num_freqs)
		dev_warn(&profile->pdev->dev, "dvfs table had no applicable frequencies!\n");

	profile->devfreq_profile.freq_table = (unsigned long *)freqs;
	profile->devfreq_profile.max_state = num_freqs;

	return 0;
}
static int gk20a_scale_make_freq_table(struct gk20a_scale_profile *profile)
{
	struct gk20a *g = get_gk20a(profile->pdev);
	unsigned long *freqs;
	int num_freqs, err;

	/* make sure the clock is available */
	if (!gk20a_clk_get(g))
		return -ENOSYS;

	/* get gpu dvfs table */
	err = tegra_dvfs_get_freqs(clk_get_parent(g->clk.tegra_clk),
				   &freqs, &num_freqs);
	if (err)
		return -ENOSYS;

	profile->devfreq_profile.freq_table = (unsigned long *)freqs;
	profile->devfreq_profile.max_state = num_freqs;

	return 0;
}
Example #3
0
static int gk20a_init_clk_setup_sw(struct gk20a *g)
{
	struct clk_gk20a *clk = &g->clk;
	static int initialized;
	unsigned long *freqs;
	int err, num_freqs;
	struct clk *ref;
	unsigned long ref_rate;

	nvhost_dbg_fn("");

	if (clk->sw_ready) {
		nvhost_dbg_fn("skip init");
		return 0;
	}

	if (!gk20a_clk_get(g))
		return -EINVAL;

	ref = clk_get_parent(clk_get_parent(clk->tegra_clk));
	if (IS_ERR(ref)) {
		nvhost_err(dev_from_gk20a(g),
			"failed to get GPCPLL reference clock");
		return -EINVAL;
	}
	ref_rate = clk_get_rate(ref);

	clk->pll_delay = 300; /* usec */

	clk->gpc_pll.id = GK20A_GPC_PLL;
	clk->gpc_pll.clk_in = ref_rate / 1000000; /* MHz */

	/* Decide initial frequency */
	if (!initialized) {
		initialized = 1;
		clk->gpc_pll.M = 1;
		clk->gpc_pll.N = DIV_ROUND_UP(gpc_pll_params.min_vco,
					clk->gpc_pll.clk_in);
		clk->gpc_pll.PL = 1;
		clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N;
		clk->gpc_pll.freq /= pl_to_div[clk->gpc_pll.PL];
	}

	err = tegra_dvfs_get_freqs(clk_get_parent(clk->tegra_clk),
				   &freqs, &num_freqs);
	if (!err) {
		int i, j;

		/* init j for inverse traversal of frequencies */
		j = num_freqs - 1;

		gpu_cooling_freq = kzalloc(
				(1 + num_freqs) * sizeof(*gpu_cooling_freq),
				GFP_KERNEL);

		/* store frequencies in inverse order */
		for (i = 0; i < num_freqs; ++i, --j) {
			gpu_cooling_freq[i].index = i;
			gpu_cooling_freq[i].frequency = freqs[j];
		}

		/* add 'end of table' marker */
		gpu_cooling_freq[i].index = i;
		gpu_cooling_freq[i].frequency = GPUFREQ_TABLE_END;

		/* store number of frequencies */
		num_gpu_cooling_freq = num_freqs + 1;
	}

	mutex_init(&clk->clk_mutex);

	clk->sw_ready = true;

	nvhost_dbg_fn("done");
	return 0;
}