13dcbd36fSThierry Reding // SPDX-License-Identifier: GPL-2.0-only 23dcbd36fSThierry Reding /* 33dcbd36fSThierry Reding * drivers/clk/tegra/clk-emc.c 43dcbd36fSThierry Reding * 53dcbd36fSThierry Reding * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 63dcbd36fSThierry Reding * 73dcbd36fSThierry Reding * Author: 83dcbd36fSThierry Reding * Mikko Perttunen <mperttunen@nvidia.com> 93dcbd36fSThierry Reding */ 103dcbd36fSThierry Reding 113dcbd36fSThierry Reding #include <linux/clk-provider.h> 123dcbd36fSThierry Reding #include <linux/clk.h> 133dcbd36fSThierry Reding #include <linux/clkdev.h> 14281462e5SDmitry Osipenko #include <linux/clk/tegra.h> 153dcbd36fSThierry Reding #include <linux/delay.h> 16281462e5SDmitry Osipenko #include <linux/export.h> 173dcbd36fSThierry Reding #include <linux/io.h> 183dcbd36fSThierry Reding #include <linux/module.h> 193dcbd36fSThierry Reding #include <linux/of_address.h> 203dcbd36fSThierry Reding #include <linux/of_platform.h> 213dcbd36fSThierry Reding #include <linux/platform_device.h> 223dcbd36fSThierry Reding #include <linux/sort.h> 233dcbd36fSThierry Reding #include <linux/string.h> 243dcbd36fSThierry Reding 253dcbd36fSThierry Reding #include <soc/tegra/fuse.h> 263dcbd36fSThierry Reding 273dcbd36fSThierry Reding #include "clk.h" 283dcbd36fSThierry Reding 293dcbd36fSThierry Reding #define CLK_SOURCE_EMC 0x19c 303dcbd36fSThierry Reding 313dcbd36fSThierry Reding #define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_SHIFT 0 323dcbd36fSThierry Reding #define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK 0xff 333dcbd36fSThierry Reding #define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(x) (((x) & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK) << \ 343dcbd36fSThierry Reding CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_SHIFT) 353dcbd36fSThierry Reding 363dcbd36fSThierry Reding #define CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT 29 373dcbd36fSThierry Reding #define CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK 0x7 383dcbd36fSThierry Reding #define CLK_SOURCE_EMC_EMC_2X_CLK_SRC(x) (((x) & CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK) << \ 393dcbd36fSThierry Reding CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT) 403dcbd36fSThierry Reding 413dcbd36fSThierry Reding static const char * const emc_parent_clk_names[] = { 423dcbd36fSThierry Reding "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", 433dcbd36fSThierry Reding "pll_c2", "pll_c3", "pll_c_ud" 443dcbd36fSThierry Reding }; 453dcbd36fSThierry Reding 463dcbd36fSThierry Reding /* 473dcbd36fSThierry Reding * List of clock sources for various parents the EMC clock can have. 483dcbd36fSThierry Reding * When we change the timing to a timing with a parent that has the same 493dcbd36fSThierry Reding * clock source as the current parent, we must first change to a backup 503dcbd36fSThierry Reding * timing that has a different clock source. 513dcbd36fSThierry Reding */ 523dcbd36fSThierry Reding 533dcbd36fSThierry Reding #define EMC_SRC_PLL_M 0 543dcbd36fSThierry Reding #define EMC_SRC_PLL_C 1 553dcbd36fSThierry Reding #define EMC_SRC_PLL_P 2 563dcbd36fSThierry Reding #define EMC_SRC_CLK_M 3 573dcbd36fSThierry Reding #define EMC_SRC_PLL_C2 4 583dcbd36fSThierry Reding #define EMC_SRC_PLL_C3 5 593dcbd36fSThierry Reding 603dcbd36fSThierry Reding static const char emc_parent_clk_sources[] = { 613dcbd36fSThierry Reding EMC_SRC_PLL_M, EMC_SRC_PLL_C, EMC_SRC_PLL_P, EMC_SRC_CLK_M, 623dcbd36fSThierry Reding EMC_SRC_PLL_M, EMC_SRC_PLL_C2, EMC_SRC_PLL_C3, EMC_SRC_PLL_C 633dcbd36fSThierry Reding }; 643dcbd36fSThierry Reding 653dcbd36fSThierry Reding struct emc_timing { 663dcbd36fSThierry Reding unsigned long rate, parent_rate; 673dcbd36fSThierry Reding u8 parent_index; 683dcbd36fSThierry Reding struct clk *parent; 693dcbd36fSThierry Reding u32 ram_code; 703dcbd36fSThierry Reding }; 713dcbd36fSThierry Reding 723dcbd36fSThierry Reding struct tegra_clk_emc { 733dcbd36fSThierry Reding struct clk_hw hw; 743dcbd36fSThierry Reding void __iomem *clk_regs; 753dcbd36fSThierry Reding struct clk *prev_parent; 763dcbd36fSThierry Reding bool changing_timing; 773dcbd36fSThierry Reding 783dcbd36fSThierry Reding struct device_node *emc_node; 793dcbd36fSThierry Reding struct tegra_emc *emc; 803dcbd36fSThierry Reding 813dcbd36fSThierry Reding int num_timings; 823dcbd36fSThierry Reding struct emc_timing *timings; 833dcbd36fSThierry Reding spinlock_t *lock; 84281462e5SDmitry Osipenko 85281462e5SDmitry Osipenko tegra124_emc_prepare_timing_change_cb *prepare_timing_change; 86281462e5SDmitry Osipenko tegra124_emc_complete_timing_change_cb *complete_timing_change; 873dcbd36fSThierry Reding }; 883dcbd36fSThierry Reding 893dcbd36fSThierry Reding /* Common clock framework callback implementations */ 903dcbd36fSThierry Reding 913dcbd36fSThierry Reding static unsigned long emc_recalc_rate(struct clk_hw *hw, 923dcbd36fSThierry Reding unsigned long parent_rate) 933dcbd36fSThierry Reding { 943dcbd36fSThierry Reding struct tegra_clk_emc *tegra; 953dcbd36fSThierry Reding u32 val, div; 963dcbd36fSThierry Reding 973dcbd36fSThierry Reding tegra = container_of(hw, struct tegra_clk_emc, hw); 983dcbd36fSThierry Reding 993dcbd36fSThierry Reding /* 1003dcbd36fSThierry Reding * CCF wrongly assumes that the parent won't change during set_rate, 1013dcbd36fSThierry Reding * so get the parent rate explicitly. 1023dcbd36fSThierry Reding */ 1033dcbd36fSThierry Reding parent_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); 1043dcbd36fSThierry Reding 1053dcbd36fSThierry Reding val = readl(tegra->clk_regs + CLK_SOURCE_EMC); 1063dcbd36fSThierry Reding div = val & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK; 1073dcbd36fSThierry Reding 1083dcbd36fSThierry Reding return parent_rate / (div + 2) * 2; 1093dcbd36fSThierry Reding } 1103dcbd36fSThierry Reding 1113dcbd36fSThierry Reding /* 1123dcbd36fSThierry Reding * Rounds up unless no higher rate exists, in which case down. This way is 1133dcbd36fSThierry Reding * safer since things have EMC rate floors. Also don't touch parent_rate 1143dcbd36fSThierry Reding * since we don't want the CCF to play with our parent clocks. 1153dcbd36fSThierry Reding */ 1163dcbd36fSThierry Reding static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) 1173dcbd36fSThierry Reding { 1183dcbd36fSThierry Reding struct tegra_clk_emc *tegra; 1193dcbd36fSThierry Reding u8 ram_code = tegra_read_ram_code(); 1203dcbd36fSThierry Reding struct emc_timing *timing = NULL; 1213dcbd36fSThierry Reding int i, k, t; 1223dcbd36fSThierry Reding 1233dcbd36fSThierry Reding tegra = container_of(hw, struct tegra_clk_emc, hw); 1243dcbd36fSThierry Reding 1253dcbd36fSThierry Reding for (k = 0; k < tegra->num_timings; k++) { 1263dcbd36fSThierry Reding if (tegra->timings[k].ram_code == ram_code) 1273dcbd36fSThierry Reding break; 1283dcbd36fSThierry Reding } 1293dcbd36fSThierry Reding 1303dcbd36fSThierry Reding for (t = k; t < tegra->num_timings; t++) { 1313dcbd36fSThierry Reding if (tegra->timings[t].ram_code != ram_code) 1323dcbd36fSThierry Reding break; 1333dcbd36fSThierry Reding } 1343dcbd36fSThierry Reding 1353dcbd36fSThierry Reding for (i = k; i < t; i++) { 1363dcbd36fSThierry Reding timing = tegra->timings + i; 1373dcbd36fSThierry Reding 1383dcbd36fSThierry Reding if (timing->rate < req->rate && i != t - 1) 1393dcbd36fSThierry Reding continue; 1403dcbd36fSThierry Reding 1413dcbd36fSThierry Reding if (timing->rate > req->max_rate) { 1423dcbd36fSThierry Reding i = max(i, k + 1); 1433dcbd36fSThierry Reding req->rate = tegra->timings[i - 1].rate; 1443dcbd36fSThierry Reding return 0; 1453dcbd36fSThierry Reding } 1463dcbd36fSThierry Reding 1473dcbd36fSThierry Reding if (timing->rate < req->min_rate) 1483dcbd36fSThierry Reding continue; 1493dcbd36fSThierry Reding 1503dcbd36fSThierry Reding req->rate = timing->rate; 1513dcbd36fSThierry Reding return 0; 1523dcbd36fSThierry Reding } 1533dcbd36fSThierry Reding 1543dcbd36fSThierry Reding if (timing) { 1553dcbd36fSThierry Reding req->rate = timing->rate; 1563dcbd36fSThierry Reding return 0; 1573dcbd36fSThierry Reding } 1583dcbd36fSThierry Reding 1593dcbd36fSThierry Reding req->rate = clk_hw_get_rate(hw); 1603dcbd36fSThierry Reding return 0; 1613dcbd36fSThierry Reding } 1623dcbd36fSThierry Reding 1633dcbd36fSThierry Reding static u8 emc_get_parent(struct clk_hw *hw) 1643dcbd36fSThierry Reding { 1653dcbd36fSThierry Reding struct tegra_clk_emc *tegra; 1663dcbd36fSThierry Reding u32 val; 1673dcbd36fSThierry Reding 1683dcbd36fSThierry Reding tegra = container_of(hw, struct tegra_clk_emc, hw); 1693dcbd36fSThierry Reding 1703dcbd36fSThierry Reding val = readl(tegra->clk_regs + CLK_SOURCE_EMC); 1713dcbd36fSThierry Reding 1723dcbd36fSThierry Reding return (val >> CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT) 1733dcbd36fSThierry Reding & CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK; 1743dcbd36fSThierry Reding } 1753dcbd36fSThierry Reding 1763dcbd36fSThierry Reding static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra) 1773dcbd36fSThierry Reding { 1783dcbd36fSThierry Reding struct platform_device *pdev; 1793dcbd36fSThierry Reding 1803dcbd36fSThierry Reding if (tegra->emc) 1813dcbd36fSThierry Reding return tegra->emc; 1823dcbd36fSThierry Reding 183281462e5SDmitry Osipenko if (!tegra->prepare_timing_change || !tegra->complete_timing_change) 184281462e5SDmitry Osipenko return NULL; 185281462e5SDmitry Osipenko 1863dcbd36fSThierry Reding if (!tegra->emc_node) 1873dcbd36fSThierry Reding return NULL; 1883dcbd36fSThierry Reding 1893dcbd36fSThierry Reding pdev = of_find_device_by_node(tegra->emc_node); 1903dcbd36fSThierry Reding if (!pdev) { 1913dcbd36fSThierry Reding pr_err("%s: could not get external memory controller\n", 1923dcbd36fSThierry Reding __func__); 1933dcbd36fSThierry Reding return NULL; 1943dcbd36fSThierry Reding } 1953dcbd36fSThierry Reding 1963dcbd36fSThierry Reding of_node_put(tegra->emc_node); 1973dcbd36fSThierry Reding tegra->emc_node = NULL; 1983dcbd36fSThierry Reding 1993dcbd36fSThierry Reding tegra->emc = platform_get_drvdata(pdev); 2003dcbd36fSThierry Reding if (!tegra->emc) { 2013dcbd36fSThierry Reding pr_err("%s: cannot find EMC driver\n", __func__); 2023dcbd36fSThierry Reding return NULL; 2033dcbd36fSThierry Reding } 2043dcbd36fSThierry Reding 2053dcbd36fSThierry Reding return tegra->emc; 2063dcbd36fSThierry Reding } 2073dcbd36fSThierry Reding 2083dcbd36fSThierry Reding static int emc_set_timing(struct tegra_clk_emc *tegra, 2093dcbd36fSThierry Reding struct emc_timing *timing) 2103dcbd36fSThierry Reding { 2113dcbd36fSThierry Reding int err; 2123dcbd36fSThierry Reding u8 div; 2133dcbd36fSThierry Reding u32 car_value; 2143dcbd36fSThierry Reding unsigned long flags = 0; 2153dcbd36fSThierry Reding struct tegra_emc *emc = emc_ensure_emc_driver(tegra); 2163dcbd36fSThierry Reding 2173dcbd36fSThierry Reding if (!emc) 2183dcbd36fSThierry Reding return -ENOENT; 2193dcbd36fSThierry Reding 2203dcbd36fSThierry Reding pr_debug("going to rate %ld prate %ld p %s\n", timing->rate, 2213dcbd36fSThierry Reding timing->parent_rate, __clk_get_name(timing->parent)); 2223dcbd36fSThierry Reding 2233dcbd36fSThierry Reding if (emc_get_parent(&tegra->hw) == timing->parent_index && 2243dcbd36fSThierry Reding clk_get_rate(timing->parent) != timing->parent_rate) { 2253dcbd36fSThierry Reding WARN_ONCE(1, "parent %s rate mismatch %lu %lu\n", 2263dcbd36fSThierry Reding __clk_get_name(timing->parent), 2273dcbd36fSThierry Reding clk_get_rate(timing->parent), 2283dcbd36fSThierry Reding timing->parent_rate); 2293dcbd36fSThierry Reding return -EINVAL; 2303dcbd36fSThierry Reding } 2313dcbd36fSThierry Reding 2323dcbd36fSThierry Reding tegra->changing_timing = true; 2333dcbd36fSThierry Reding 2343dcbd36fSThierry Reding err = clk_set_rate(timing->parent, timing->parent_rate); 2353dcbd36fSThierry Reding if (err) { 2363dcbd36fSThierry Reding pr_err("cannot change parent %s rate to %ld: %d\n", 2373dcbd36fSThierry Reding __clk_get_name(timing->parent), timing->parent_rate, 2383dcbd36fSThierry Reding err); 2393dcbd36fSThierry Reding 2403dcbd36fSThierry Reding return err; 2413dcbd36fSThierry Reding } 2423dcbd36fSThierry Reding 2433dcbd36fSThierry Reding err = clk_prepare_enable(timing->parent); 2443dcbd36fSThierry Reding if (err) { 2453dcbd36fSThierry Reding pr_err("cannot enable parent clock: %d\n", err); 2463dcbd36fSThierry Reding return err; 2473dcbd36fSThierry Reding } 2483dcbd36fSThierry Reding 2493dcbd36fSThierry Reding div = timing->parent_rate / (timing->rate / 2) - 2; 2503dcbd36fSThierry Reding 251281462e5SDmitry Osipenko err = tegra->prepare_timing_change(emc, timing->rate); 252*f13570e7SYang Yingliang if (err) { 253*f13570e7SYang Yingliang clk_disable_unprepare(timing->parent); 2543dcbd36fSThierry Reding return err; 255*f13570e7SYang Yingliang } 2563dcbd36fSThierry Reding 2573dcbd36fSThierry Reding spin_lock_irqsave(tegra->lock, flags); 2583dcbd36fSThierry Reding 2593dcbd36fSThierry Reding car_value = readl(tegra->clk_regs + CLK_SOURCE_EMC); 2603dcbd36fSThierry Reding 2613dcbd36fSThierry Reding car_value &= ~CLK_SOURCE_EMC_EMC_2X_CLK_SRC(~0); 2623dcbd36fSThierry Reding car_value |= CLK_SOURCE_EMC_EMC_2X_CLK_SRC(timing->parent_index); 2633dcbd36fSThierry Reding 2643dcbd36fSThierry Reding car_value &= ~CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(~0); 2653dcbd36fSThierry Reding car_value |= CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(div); 2663dcbd36fSThierry Reding 2673dcbd36fSThierry Reding writel(car_value, tegra->clk_regs + CLK_SOURCE_EMC); 2683dcbd36fSThierry Reding 2693dcbd36fSThierry Reding spin_unlock_irqrestore(tegra->lock, flags); 2703dcbd36fSThierry Reding 271281462e5SDmitry Osipenko tegra->complete_timing_change(emc, timing->rate); 2723dcbd36fSThierry Reding 2733dcbd36fSThierry Reding clk_hw_reparent(&tegra->hw, __clk_get_hw(timing->parent)); 2743dcbd36fSThierry Reding clk_disable_unprepare(tegra->prev_parent); 2753dcbd36fSThierry Reding 2763dcbd36fSThierry Reding tegra->prev_parent = timing->parent; 2773dcbd36fSThierry Reding tegra->changing_timing = false; 2783dcbd36fSThierry Reding 2793dcbd36fSThierry Reding return 0; 2803dcbd36fSThierry Reding } 2813dcbd36fSThierry Reding 2823dcbd36fSThierry Reding /* 2833dcbd36fSThierry Reding * Get backup timing to use as an intermediate step when a change between 2843dcbd36fSThierry Reding * two timings with the same clock source has been requested. First try to 2853dcbd36fSThierry Reding * find a timing with a higher clock rate to avoid a rate below any set rate 2863dcbd36fSThierry Reding * floors. If that is not possible, find a lower rate. 2873dcbd36fSThierry Reding */ 2883dcbd36fSThierry Reding static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra, 2893dcbd36fSThierry Reding int timing_index) 2903dcbd36fSThierry Reding { 2913dcbd36fSThierry Reding int i; 2923dcbd36fSThierry Reding u32 ram_code = tegra_read_ram_code(); 2933dcbd36fSThierry Reding struct emc_timing *timing; 2943dcbd36fSThierry Reding 2953dcbd36fSThierry Reding for (i = timing_index+1; i < tegra->num_timings; i++) { 2963dcbd36fSThierry Reding timing = tegra->timings + i; 2973dcbd36fSThierry Reding if (timing->ram_code != ram_code) 2983dcbd36fSThierry Reding break; 2993dcbd36fSThierry Reding 3003dcbd36fSThierry Reding if (emc_parent_clk_sources[timing->parent_index] != 3013dcbd36fSThierry Reding emc_parent_clk_sources[ 3023dcbd36fSThierry Reding tegra->timings[timing_index].parent_index]) 3033dcbd36fSThierry Reding return timing; 3043dcbd36fSThierry Reding } 3053dcbd36fSThierry Reding 3063dcbd36fSThierry Reding for (i = timing_index-1; i >= 0; --i) { 3073dcbd36fSThierry Reding timing = tegra->timings + i; 3083dcbd36fSThierry Reding if (timing->ram_code != ram_code) 3093dcbd36fSThierry Reding break; 3103dcbd36fSThierry Reding 3113dcbd36fSThierry Reding if (emc_parent_clk_sources[timing->parent_index] != 3123dcbd36fSThierry Reding emc_parent_clk_sources[ 3133dcbd36fSThierry Reding tegra->timings[timing_index].parent_index]) 3143dcbd36fSThierry Reding return timing; 3153dcbd36fSThierry Reding } 3163dcbd36fSThierry Reding 3173dcbd36fSThierry Reding return NULL; 3183dcbd36fSThierry Reding } 3193dcbd36fSThierry Reding 3203dcbd36fSThierry Reding static int emc_set_rate(struct clk_hw *hw, unsigned long rate, 3213dcbd36fSThierry Reding unsigned long parent_rate) 3223dcbd36fSThierry Reding { 3233dcbd36fSThierry Reding struct tegra_clk_emc *tegra; 3243dcbd36fSThierry Reding struct emc_timing *timing = NULL; 3253dcbd36fSThierry Reding int i, err; 3263dcbd36fSThierry Reding u32 ram_code = tegra_read_ram_code(); 3273dcbd36fSThierry Reding 3283dcbd36fSThierry Reding tegra = container_of(hw, struct tegra_clk_emc, hw); 3293dcbd36fSThierry Reding 3303dcbd36fSThierry Reding if (clk_hw_get_rate(hw) == rate) 3313dcbd36fSThierry Reding return 0; 3323dcbd36fSThierry Reding 3333dcbd36fSThierry Reding /* 3343dcbd36fSThierry Reding * When emc_set_timing changes the parent rate, CCF will propagate 3353dcbd36fSThierry Reding * that downward to us, so ignore any set_rate calls while a rate 3363dcbd36fSThierry Reding * change is already going on. 3373dcbd36fSThierry Reding */ 3383dcbd36fSThierry Reding if (tegra->changing_timing) 3393dcbd36fSThierry Reding return 0; 3403dcbd36fSThierry Reding 3413dcbd36fSThierry Reding for (i = 0; i < tegra->num_timings; i++) { 3423dcbd36fSThierry Reding if (tegra->timings[i].rate == rate && 3433dcbd36fSThierry Reding tegra->timings[i].ram_code == ram_code) { 3443dcbd36fSThierry Reding timing = tegra->timings + i; 3453dcbd36fSThierry Reding break; 3463dcbd36fSThierry Reding } 3473dcbd36fSThierry Reding } 3483dcbd36fSThierry Reding 3493dcbd36fSThierry Reding if (!timing) { 3503dcbd36fSThierry Reding pr_err("cannot switch to rate %ld without emc table\n", rate); 3513dcbd36fSThierry Reding return -EINVAL; 3523dcbd36fSThierry Reding } 3533dcbd36fSThierry Reding 3543dcbd36fSThierry Reding if (emc_parent_clk_sources[emc_get_parent(hw)] == 3553dcbd36fSThierry Reding emc_parent_clk_sources[timing->parent_index] && 3563dcbd36fSThierry Reding clk_get_rate(timing->parent) != timing->parent_rate) { 3573dcbd36fSThierry Reding /* 3583dcbd36fSThierry Reding * Parent clock source not changed but parent rate has changed, 3593dcbd36fSThierry Reding * need to temporarily switch to another parent 3603dcbd36fSThierry Reding */ 3613dcbd36fSThierry Reding 3623dcbd36fSThierry Reding struct emc_timing *backup_timing; 3633dcbd36fSThierry Reding 3643dcbd36fSThierry Reding backup_timing = get_backup_timing(tegra, i); 3653dcbd36fSThierry Reding if (!backup_timing) { 3663dcbd36fSThierry Reding pr_err("cannot find backup timing\n"); 3673dcbd36fSThierry Reding return -EINVAL; 3683dcbd36fSThierry Reding } 3693dcbd36fSThierry Reding 3703dcbd36fSThierry Reding pr_debug("using %ld as backup rate when going to %ld\n", 3713dcbd36fSThierry Reding backup_timing->rate, rate); 3723dcbd36fSThierry Reding 3733dcbd36fSThierry Reding err = emc_set_timing(tegra, backup_timing); 3743dcbd36fSThierry Reding if (err) { 3753dcbd36fSThierry Reding pr_err("cannot set backup timing: %d\n", err); 3763dcbd36fSThierry Reding return err; 3773dcbd36fSThierry Reding } 3783dcbd36fSThierry Reding } 3793dcbd36fSThierry Reding 3803dcbd36fSThierry Reding return emc_set_timing(tegra, timing); 3813dcbd36fSThierry Reding } 3823dcbd36fSThierry Reding 3833dcbd36fSThierry Reding /* Initialization and deinitialization */ 3843dcbd36fSThierry Reding 3853dcbd36fSThierry Reding static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, 3863dcbd36fSThierry Reding struct emc_timing *timing, 3873dcbd36fSThierry Reding struct device_node *node) 3883dcbd36fSThierry Reding { 3893dcbd36fSThierry Reding int err, i; 3903dcbd36fSThierry Reding u32 tmp; 3913dcbd36fSThierry Reding 3923dcbd36fSThierry Reding err = of_property_read_u32(node, "clock-frequency", &tmp); 3933dcbd36fSThierry Reding if (err) { 3943dcbd36fSThierry Reding pr_err("timing %pOF: failed to read rate\n", node); 3953dcbd36fSThierry Reding return err; 3963dcbd36fSThierry Reding } 3973dcbd36fSThierry Reding 3983dcbd36fSThierry Reding timing->rate = tmp; 3993dcbd36fSThierry Reding 4003dcbd36fSThierry Reding err = of_property_read_u32(node, "nvidia,parent-clock-frequency", &tmp); 4013dcbd36fSThierry Reding if (err) { 4023dcbd36fSThierry Reding pr_err("timing %pOF: failed to read parent rate\n", node); 4033dcbd36fSThierry Reding return err; 4043dcbd36fSThierry Reding } 4053dcbd36fSThierry Reding 4063dcbd36fSThierry Reding timing->parent_rate = tmp; 4073dcbd36fSThierry Reding 4083dcbd36fSThierry Reding timing->parent = of_clk_get_by_name(node, "emc-parent"); 4093dcbd36fSThierry Reding if (IS_ERR(timing->parent)) { 4103dcbd36fSThierry Reding pr_err("timing %pOF: failed to get parent clock\n", node); 4113dcbd36fSThierry Reding return PTR_ERR(timing->parent); 4123dcbd36fSThierry Reding } 4133dcbd36fSThierry Reding 4143dcbd36fSThierry Reding timing->parent_index = 0xff; 4153dcbd36fSThierry Reding i = match_string(emc_parent_clk_names, ARRAY_SIZE(emc_parent_clk_names), 4163dcbd36fSThierry Reding __clk_get_name(timing->parent)); 4173dcbd36fSThierry Reding if (i < 0) { 4183dcbd36fSThierry Reding pr_err("timing %pOF: %s is not a valid parent\n", 4193dcbd36fSThierry Reding node, __clk_get_name(timing->parent)); 4203dcbd36fSThierry Reding clk_put(timing->parent); 4213dcbd36fSThierry Reding return -EINVAL; 4223dcbd36fSThierry Reding } 4233dcbd36fSThierry Reding 4243dcbd36fSThierry Reding timing->parent_index = i; 4253dcbd36fSThierry Reding return 0; 4263dcbd36fSThierry Reding } 4273dcbd36fSThierry Reding 4283dcbd36fSThierry Reding static int cmp_timings(const void *_a, const void *_b) 4293dcbd36fSThierry Reding { 4303dcbd36fSThierry Reding const struct emc_timing *a = _a; 4313dcbd36fSThierry Reding const struct emc_timing *b = _b; 4323dcbd36fSThierry Reding 4333dcbd36fSThierry Reding if (a->rate < b->rate) 4343dcbd36fSThierry Reding return -1; 4353dcbd36fSThierry Reding else if (a->rate == b->rate) 4363dcbd36fSThierry Reding return 0; 4373dcbd36fSThierry Reding else 4383dcbd36fSThierry Reding return 1; 4393dcbd36fSThierry Reding } 4403dcbd36fSThierry Reding 4413dcbd36fSThierry Reding static int load_timings_from_dt(struct tegra_clk_emc *tegra, 4423dcbd36fSThierry Reding struct device_node *node, 4433dcbd36fSThierry Reding u32 ram_code) 4443dcbd36fSThierry Reding { 4453dcbd36fSThierry Reding struct emc_timing *timings_ptr; 4463dcbd36fSThierry Reding struct device_node *child; 4473dcbd36fSThierry Reding int child_count = of_get_child_count(node); 4483dcbd36fSThierry Reding int i = 0, err; 4493dcbd36fSThierry Reding size_t size; 4503dcbd36fSThierry Reding 4513dcbd36fSThierry Reding size = (tegra->num_timings + child_count) * sizeof(struct emc_timing); 4523dcbd36fSThierry Reding 4533dcbd36fSThierry Reding tegra->timings = krealloc(tegra->timings, size, GFP_KERNEL); 4543dcbd36fSThierry Reding if (!tegra->timings) 4553dcbd36fSThierry Reding return -ENOMEM; 4563dcbd36fSThierry Reding 4573dcbd36fSThierry Reding timings_ptr = tegra->timings + tegra->num_timings; 4583dcbd36fSThierry Reding tegra->num_timings += child_count; 4593dcbd36fSThierry Reding 4603dcbd36fSThierry Reding for_each_child_of_node(node, child) { 4613dcbd36fSThierry Reding struct emc_timing *timing = timings_ptr + (i++); 4623dcbd36fSThierry Reding 4633dcbd36fSThierry Reding err = load_one_timing_from_dt(tegra, timing, child); 4643dcbd36fSThierry Reding if (err) { 4653dcbd36fSThierry Reding of_node_put(child); 4663dcbd36fSThierry Reding return err; 4673dcbd36fSThierry Reding } 4683dcbd36fSThierry Reding 4693dcbd36fSThierry Reding timing->ram_code = ram_code; 4703dcbd36fSThierry Reding } 4713dcbd36fSThierry Reding 4723dcbd36fSThierry Reding sort(timings_ptr, child_count, sizeof(struct emc_timing), 4733dcbd36fSThierry Reding cmp_timings, NULL); 4743dcbd36fSThierry Reding 4753dcbd36fSThierry Reding return 0; 4763dcbd36fSThierry Reding } 4773dcbd36fSThierry Reding 4783dcbd36fSThierry Reding static const struct clk_ops tegra_clk_emc_ops = { 4793dcbd36fSThierry Reding .recalc_rate = emc_recalc_rate, 4803dcbd36fSThierry Reding .determine_rate = emc_determine_rate, 4813dcbd36fSThierry Reding .set_rate = emc_set_rate, 4823dcbd36fSThierry Reding .get_parent = emc_get_parent, 4833dcbd36fSThierry Reding }; 4843dcbd36fSThierry Reding 485281462e5SDmitry Osipenko struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np, 4863dcbd36fSThierry Reding spinlock_t *lock) 4873dcbd36fSThierry Reding { 4883dcbd36fSThierry Reding struct tegra_clk_emc *tegra; 4893dcbd36fSThierry Reding struct clk_init_data init; 4903dcbd36fSThierry Reding struct device_node *node; 4913dcbd36fSThierry Reding u32 node_ram_code; 4923dcbd36fSThierry Reding struct clk *clk; 4933dcbd36fSThierry Reding int err; 4943dcbd36fSThierry Reding 4953dcbd36fSThierry Reding tegra = kcalloc(1, sizeof(*tegra), GFP_KERNEL); 4963dcbd36fSThierry Reding if (!tegra) 4973dcbd36fSThierry Reding return ERR_PTR(-ENOMEM); 4983dcbd36fSThierry Reding 4993dcbd36fSThierry Reding tegra->clk_regs = base; 5003dcbd36fSThierry Reding tegra->lock = lock; 5013dcbd36fSThierry Reding 5023dcbd36fSThierry Reding tegra->num_timings = 0; 5033dcbd36fSThierry Reding 5043dcbd36fSThierry Reding for_each_child_of_node(np, node) { 5053dcbd36fSThierry Reding err = of_property_read_u32(node, "nvidia,ram-code", 5063dcbd36fSThierry Reding &node_ram_code); 5073dcbd36fSThierry Reding if (err) 5083dcbd36fSThierry Reding continue; 5093dcbd36fSThierry Reding 5103dcbd36fSThierry Reding /* 5113dcbd36fSThierry Reding * Store timings for all ram codes as we cannot read the 5123dcbd36fSThierry Reding * fuses until the apbmisc driver is loaded. 5133dcbd36fSThierry Reding */ 5143dcbd36fSThierry Reding err = load_timings_from_dt(tegra, node, node_ram_code); 5153dcbd36fSThierry Reding if (err) { 5163dcbd36fSThierry Reding of_node_put(node); 5173dcbd36fSThierry Reding return ERR_PTR(err); 5183dcbd36fSThierry Reding } 5193dcbd36fSThierry Reding } 5203dcbd36fSThierry Reding 5213dcbd36fSThierry Reding if (tegra->num_timings == 0) 5223dcbd36fSThierry Reding pr_warn("%s: no memory timings registered\n", __func__); 5233dcbd36fSThierry Reding 5243dcbd36fSThierry Reding tegra->emc_node = of_parse_phandle(np, 5253dcbd36fSThierry Reding "nvidia,external-memory-controller", 0); 5263dcbd36fSThierry Reding if (!tegra->emc_node) 5273dcbd36fSThierry Reding pr_warn("%s: couldn't find node for EMC driver\n", __func__); 5283dcbd36fSThierry Reding 5293dcbd36fSThierry Reding init.name = "emc"; 5303dcbd36fSThierry Reding init.ops = &tegra_clk_emc_ops; 5313dcbd36fSThierry Reding init.flags = CLK_IS_CRITICAL; 5323dcbd36fSThierry Reding init.parent_names = emc_parent_clk_names; 5333dcbd36fSThierry Reding init.num_parents = ARRAY_SIZE(emc_parent_clk_names); 5343dcbd36fSThierry Reding 5353dcbd36fSThierry Reding tegra->hw.init = &init; 5363dcbd36fSThierry Reding 5373dcbd36fSThierry Reding clk = clk_register(NULL, &tegra->hw); 5383dcbd36fSThierry Reding if (IS_ERR(clk)) 5393dcbd36fSThierry Reding return clk; 5403dcbd36fSThierry Reding 5413dcbd36fSThierry Reding tegra->prev_parent = clk_hw_get_parent_by_index( 5423dcbd36fSThierry Reding &tegra->hw, emc_get_parent(&tegra->hw))->clk; 5433dcbd36fSThierry Reding tegra->changing_timing = false; 5443dcbd36fSThierry Reding 5453dcbd36fSThierry Reding /* Allow debugging tools to see the EMC clock */ 5463dcbd36fSThierry Reding clk_register_clkdev(clk, "emc", "tegra-clk-debug"); 5473dcbd36fSThierry Reding 5483dcbd36fSThierry Reding return clk; 5493dcbd36fSThierry Reding }; 550281462e5SDmitry Osipenko 551281462e5SDmitry Osipenko void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, 552281462e5SDmitry Osipenko tegra124_emc_complete_timing_change_cb *complete_cb) 553281462e5SDmitry Osipenko { 554281462e5SDmitry Osipenko struct clk *clk = __clk_lookup("emc"); 555281462e5SDmitry Osipenko struct tegra_clk_emc *tegra; 556281462e5SDmitry Osipenko struct clk_hw *hw; 557281462e5SDmitry Osipenko 558281462e5SDmitry Osipenko if (clk) { 559281462e5SDmitry Osipenko hw = __clk_get_hw(clk); 560281462e5SDmitry Osipenko tegra = container_of(hw, struct tegra_clk_emc, hw); 561281462e5SDmitry Osipenko 562281462e5SDmitry Osipenko tegra->prepare_timing_change = prep_cb; 563281462e5SDmitry Osipenko tegra->complete_timing_change = complete_cb; 564281462e5SDmitry Osipenko } 565281462e5SDmitry Osipenko } 566281462e5SDmitry Osipenko EXPORT_SYMBOL_GPL(tegra124_clk_set_emc_callbacks); 567281462e5SDmitry Osipenko 568281462e5SDmitry Osipenko bool tegra124_clk_emc_driver_available(struct clk_hw *hw) 569281462e5SDmitry Osipenko { 570281462e5SDmitry Osipenko struct tegra_clk_emc *tegra = container_of(hw, struct tegra_clk_emc, hw); 571281462e5SDmitry Osipenko 572281462e5SDmitry Osipenko return tegra->prepare_timing_change && tegra->complete_timing_change; 573281462e5SDmitry Osipenko } 574