Commit 77ab499d authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Thierry Reding
Browse files

memory: tegra: Adapt for Tegra20 clock driver changes



Now Tegra20 and Tegra30 EMC drivers should provide clock-rounding
functionality using the new Tegra clock driver API.

Acked-by: default avatarPeter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent fa6749d4
Loading
Loading
Loading
Loading
+48 −2
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
 */

#include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/completion.h>
#include <linux/err.h>
#include <linux/interrupt.h>
@@ -421,6 +422,44 @@ static int emc_setup_hw(struct tegra_emc *emc)
	return 0;
}

static long emc_round_rate(unsigned long rate,
			   unsigned long min_rate,
			   unsigned long max_rate,
			   void *arg)
{
	struct emc_timing *timing = NULL;
	struct tegra_emc *emc = arg;
	unsigned int i;

	min_rate = min(min_rate, emc->timings[emc->num_timings - 1].rate);

	for (i = 0; i < emc->num_timings; i++) {
		if (emc->timings[i].rate < rate && i != emc->num_timings - 1)
			continue;

		if (emc->timings[i].rate > max_rate) {
			i = max(i, 1u) - 1;

			if (emc->timings[i].rate < min_rate)
				break;
		}

		if (emc->timings[i].rate < min_rate)
			continue;

		timing = &emc->timings[i];
		break;
	}

	if (!timing) {
		dev_err(emc->dev, "no timing for rate %lu min %lu max %lu\n",
			rate, min_rate, max_rate);
		return -EINVAL;
	}

	return timing->rate;
}

static int tegra_emc_probe(struct platform_device *pdev)
{
	struct device_node *np;
@@ -477,21 +516,28 @@ static int tegra_emc_probe(struct platform_device *pdev)
		return err;
	}

	tegra20_clk_set_emc_round_callback(emc_round_rate, emc);

	emc->clk = devm_clk_get(&pdev->dev, "emc");
	if (IS_ERR(emc->clk)) {
		err = PTR_ERR(emc->clk);
		dev_err(&pdev->dev, "failed to get emc clock: %d\n", err);
		return err;
		goto unset_cb;
	}

	err = clk_notifier_register(emc->clk, &emc->clk_nb);
	if (err) {
		dev_err(&pdev->dev, "failed to register clk notifier: %d\n",
			err);
		return err;
		goto unset_cb;
	}

	return 0;

unset_cb:
	tegra20_clk_set_emc_round_callback(NULL, NULL);

	return err;
}

static const struct of_device_id tegra_emc_of_match[] = {