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: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Dmitry Osipenko 2019-08-12 00:00:31 +03:00 committed by Thierry Reding
parent fa6749d40e
commit 77ab499dca
1 changed files with 48 additions and 2 deletions

View File

@ -6,6 +6,7 @@
*/ */
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk/tegra.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
@ -421,6 +422,44 @@ static int emc_setup_hw(struct tegra_emc *emc)
return 0; 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) static int tegra_emc_probe(struct platform_device *pdev)
{ {
struct device_node *np; struct device_node *np;
@ -477,21 +516,28 @@ static int tegra_emc_probe(struct platform_device *pdev)
return err; return err;
} }
tegra20_clk_set_emc_round_callback(emc_round_rate, emc);
emc->clk = devm_clk_get(&pdev->dev, "emc"); emc->clk = devm_clk_get(&pdev->dev, "emc");
if (IS_ERR(emc->clk)) { if (IS_ERR(emc->clk)) {
err = PTR_ERR(emc->clk); err = PTR_ERR(emc->clk);
dev_err(&pdev->dev, "failed to get emc clock: %d\n", err); 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); err = clk_notifier_register(emc->clk, &emc->clk_nb);
if (err) { if (err) {
dev_err(&pdev->dev, "failed to register clk notifier: %d\n", dev_err(&pdev->dev, "failed to register clk notifier: %d\n",
err); err);
return err; goto unset_cb;
} }
return 0; return 0;
unset_cb:
tegra20_clk_set_emc_round_callback(NULL, NULL);
return err;
} }
static const struct of_device_id tegra_emc_of_match[] = { static const struct of_device_id tegra_emc_of_match[] = {