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:
parent
fa6749d40e
commit
77ab499dca
|
@ -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[] = {
|
||||||
|
|
Loading…
Reference in New Issue