clk: tegra: emc: Support multiple RAM codes

The timings parser doesn't append timings, but instead it parses only
the first timing and hence doesn't store all of the timings when
device-tree has timings for multiple RAM codes. In a result EMC scaling
doesn't work if timings are missing.

Tested-by: Steev Klimaszewski <steev@kali.org>
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
Dmitry Osipenko 2019-04-14 22:23:18 +03:00 committed by Stephen Boyd
parent 924ee3d551
commit 888ca40e28
1 changed files with 23 additions and 14 deletions

View File

@ -121,18 +121,23 @@ static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
struct tegra_clk_emc *tegra;
u8 ram_code = tegra_read_ram_code();
struct emc_timing *timing = NULL;
int i;
int i, k;
tegra = container_of(hw, struct tegra_clk_emc, hw);
for (i = 0; i < tegra->num_timings; i++) {
for (k = 0; k < tegra->num_timings; k++) {
if (tegra->timings[k].ram_code == ram_code)
break;
}
for (i = k; i < tegra->num_timings; i++) {
if (tegra->timings[i].ram_code != ram_code)
continue;
break;
timing = tegra->timings + i;
if (timing->rate > req->max_rate) {
i = max(i, 1);
i = max(i, k + 1);
req->rate = tegra->timings[i - 1].rate;
return 0;
}
@ -282,7 +287,7 @@ static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra,
for (i = timing_index+1; i < tegra->num_timings; i++) {
timing = tegra->timings + i;
if (timing->ram_code != ram_code)
continue;
break;
if (emc_parent_clk_sources[timing->parent_index] !=
emc_parent_clk_sources[
@ -293,7 +298,7 @@ static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra,
for (i = timing_index-1; i >= 0; --i) {
timing = tegra->timings + i;
if (timing->ram_code != ram_code)
continue;
break;
if (emc_parent_clk_sources[timing->parent_index] !=
emc_parent_clk_sources[
@ -433,19 +438,23 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
struct device_node *node,
u32 ram_code)
{
struct emc_timing *timings_ptr;
struct device_node *child;
int child_count = of_get_child_count(node);
int i = 0, err;
size_t size;
tegra->timings = kcalloc(child_count, sizeof(struct emc_timing),
GFP_KERNEL);
size = (tegra->num_timings + child_count) * sizeof(struct emc_timing);
tegra->timings = krealloc(tegra->timings, size, GFP_KERNEL);
if (!tegra->timings)
return -ENOMEM;
tegra->num_timings = child_count;
timings_ptr = tegra->timings + tegra->num_timings;
tegra->num_timings += child_count;
for_each_child_of_node(node, child) {
struct emc_timing *timing = tegra->timings + (i++);
struct emc_timing *timing = timings_ptr + (i++);
err = load_one_timing_from_dt(tegra, timing, child);
if (err) {
@ -456,7 +465,7 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
timing->ram_code = ram_code;
}
sort(tegra->timings, tegra->num_timings, sizeof(struct emc_timing),
sort(timings_ptr, child_count, sizeof(struct emc_timing),
cmp_timings, NULL);
return 0;
@ -499,10 +508,10 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
* fuses until the apbmisc driver is loaded.
*/
err = load_timings_from_dt(tegra, node, node_ram_code);
of_node_put(node);
if (err)
if (err) {
of_node_put(node);
return ERR_PTR(err);
break;
}
}
if (tegra->num_timings == 0)