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:
parent
924ee3d551
commit
888ca40e28
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue