18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/clkdev.h> 78c2ecf20Sopenharmony_ci#include <linux/clk.h> 88c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 98c2ecf20Sopenharmony_ci#include <linux/delay.h> 108c2ecf20Sopenharmony_ci#include <linux/io.h> 118c2ecf20Sopenharmony_ci#include <linux/of.h> 128c2ecf20Sopenharmony_ci#include <linux/clk/tegra.h> 138c2ecf20Sopenharmony_ci#include <linux/reset-controller.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <soc/tegra/fuse.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "clk.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* Global data of Tegra CPU CAR ops */ 208c2ecf20Sopenharmony_cistatic struct tegra_cpu_car_ops dummy_car_ops; 218c2ecf20Sopenharmony_cistruct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciint *periph_clk_enb_refcnt; 248c2ecf20Sopenharmony_cistatic int periph_banks; 258c2ecf20Sopenharmony_cistatic u32 *periph_state_ctx; 268c2ecf20Sopenharmony_cistatic struct clk **clks; 278c2ecf20Sopenharmony_cistatic int clk_num; 288c2ecf20Sopenharmony_cistatic struct clk_onecell_data clk_data; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* Handlers for SoC-specific reset lines */ 318c2ecf20Sopenharmony_cistatic int (*special_reset_assert)(unsigned long); 328c2ecf20Sopenharmony_cistatic int (*special_reset_deassert)(unsigned long); 338c2ecf20Sopenharmony_cistatic unsigned int num_special_reset; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic const struct tegra_clk_periph_regs periph_regs[] = { 368c2ecf20Sopenharmony_ci [0] = { 378c2ecf20Sopenharmony_ci .enb_reg = CLK_OUT_ENB_L, 388c2ecf20Sopenharmony_ci .enb_set_reg = CLK_OUT_ENB_SET_L, 398c2ecf20Sopenharmony_ci .enb_clr_reg = CLK_OUT_ENB_CLR_L, 408c2ecf20Sopenharmony_ci .rst_reg = RST_DEVICES_L, 418c2ecf20Sopenharmony_ci .rst_set_reg = RST_DEVICES_SET_L, 428c2ecf20Sopenharmony_ci .rst_clr_reg = RST_DEVICES_CLR_L, 438c2ecf20Sopenharmony_ci }, 448c2ecf20Sopenharmony_ci [1] = { 458c2ecf20Sopenharmony_ci .enb_reg = CLK_OUT_ENB_H, 468c2ecf20Sopenharmony_ci .enb_set_reg = CLK_OUT_ENB_SET_H, 478c2ecf20Sopenharmony_ci .enb_clr_reg = CLK_OUT_ENB_CLR_H, 488c2ecf20Sopenharmony_ci .rst_reg = RST_DEVICES_H, 498c2ecf20Sopenharmony_ci .rst_set_reg = RST_DEVICES_SET_H, 508c2ecf20Sopenharmony_ci .rst_clr_reg = RST_DEVICES_CLR_H, 518c2ecf20Sopenharmony_ci }, 528c2ecf20Sopenharmony_ci [2] = { 538c2ecf20Sopenharmony_ci .enb_reg = CLK_OUT_ENB_U, 548c2ecf20Sopenharmony_ci .enb_set_reg = CLK_OUT_ENB_SET_U, 558c2ecf20Sopenharmony_ci .enb_clr_reg = CLK_OUT_ENB_CLR_U, 568c2ecf20Sopenharmony_ci .rst_reg = RST_DEVICES_U, 578c2ecf20Sopenharmony_ci .rst_set_reg = RST_DEVICES_SET_U, 588c2ecf20Sopenharmony_ci .rst_clr_reg = RST_DEVICES_CLR_U, 598c2ecf20Sopenharmony_ci }, 608c2ecf20Sopenharmony_ci [3] = { 618c2ecf20Sopenharmony_ci .enb_reg = CLK_OUT_ENB_V, 628c2ecf20Sopenharmony_ci .enb_set_reg = CLK_OUT_ENB_SET_V, 638c2ecf20Sopenharmony_ci .enb_clr_reg = CLK_OUT_ENB_CLR_V, 648c2ecf20Sopenharmony_ci .rst_reg = RST_DEVICES_V, 658c2ecf20Sopenharmony_ci .rst_set_reg = RST_DEVICES_SET_V, 668c2ecf20Sopenharmony_ci .rst_clr_reg = RST_DEVICES_CLR_V, 678c2ecf20Sopenharmony_ci }, 688c2ecf20Sopenharmony_ci [4] = { 698c2ecf20Sopenharmony_ci .enb_reg = CLK_OUT_ENB_W, 708c2ecf20Sopenharmony_ci .enb_set_reg = CLK_OUT_ENB_SET_W, 718c2ecf20Sopenharmony_ci .enb_clr_reg = CLK_OUT_ENB_CLR_W, 728c2ecf20Sopenharmony_ci .rst_reg = RST_DEVICES_W, 738c2ecf20Sopenharmony_ci .rst_set_reg = RST_DEVICES_SET_W, 748c2ecf20Sopenharmony_ci .rst_clr_reg = RST_DEVICES_CLR_W, 758c2ecf20Sopenharmony_ci }, 768c2ecf20Sopenharmony_ci [5] = { 778c2ecf20Sopenharmony_ci .enb_reg = CLK_OUT_ENB_X, 788c2ecf20Sopenharmony_ci .enb_set_reg = CLK_OUT_ENB_SET_X, 798c2ecf20Sopenharmony_ci .enb_clr_reg = CLK_OUT_ENB_CLR_X, 808c2ecf20Sopenharmony_ci .rst_reg = RST_DEVICES_X, 818c2ecf20Sopenharmony_ci .rst_set_reg = RST_DEVICES_SET_X, 828c2ecf20Sopenharmony_ci .rst_clr_reg = RST_DEVICES_CLR_X, 838c2ecf20Sopenharmony_ci }, 848c2ecf20Sopenharmony_ci [6] = { 858c2ecf20Sopenharmony_ci .enb_reg = CLK_OUT_ENB_Y, 868c2ecf20Sopenharmony_ci .enb_set_reg = CLK_OUT_ENB_SET_Y, 878c2ecf20Sopenharmony_ci .enb_clr_reg = CLK_OUT_ENB_CLR_Y, 888c2ecf20Sopenharmony_ci .rst_reg = RST_DEVICES_Y, 898c2ecf20Sopenharmony_ci .rst_set_reg = RST_DEVICES_SET_Y, 908c2ecf20Sopenharmony_ci .rst_clr_reg = RST_DEVICES_CLR_Y, 918c2ecf20Sopenharmony_ci }, 928c2ecf20Sopenharmony_ci}; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cistatic void __iomem *clk_base; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int tegra_clk_rst_assert(struct reset_controller_dev *rcdev, 978c2ecf20Sopenharmony_ci unsigned long id) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci /* 1008c2ecf20Sopenharmony_ci * If peripheral is on the APB bus then we must read the APB bus to 1018c2ecf20Sopenharmony_ci * flush the write operation in apb bus. This will avoid peripheral 1028c2ecf20Sopenharmony_ci * access after disabling clock. Since the reset driver has no 1038c2ecf20Sopenharmony_ci * knowledge of which reset IDs represent which devices, simply do 1048c2ecf20Sopenharmony_ci * this all the time. 1058c2ecf20Sopenharmony_ci */ 1068c2ecf20Sopenharmony_ci tegra_read_chipid(); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (id < periph_banks * 32) { 1098c2ecf20Sopenharmony_ci writel_relaxed(BIT(id % 32), 1108c2ecf20Sopenharmony_ci clk_base + periph_regs[id / 32].rst_set_reg); 1118c2ecf20Sopenharmony_ci return 0; 1128c2ecf20Sopenharmony_ci } else if (id < periph_banks * 32 + num_special_reset) { 1138c2ecf20Sopenharmony_ci return special_reset_assert(id); 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return -EINVAL; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, 1208c2ecf20Sopenharmony_ci unsigned long id) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci if (id < periph_banks * 32) { 1238c2ecf20Sopenharmony_ci writel_relaxed(BIT(id % 32), 1248c2ecf20Sopenharmony_ci clk_base + periph_regs[id / 32].rst_clr_reg); 1258c2ecf20Sopenharmony_ci return 0; 1268c2ecf20Sopenharmony_ci } else if (id < periph_banks * 32 + num_special_reset) { 1278c2ecf20Sopenharmony_ci return special_reset_deassert(id); 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci return -EINVAL; 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic int tegra_clk_rst_reset(struct reset_controller_dev *rcdev, 1348c2ecf20Sopenharmony_ci unsigned long id) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci int err; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci err = tegra_clk_rst_assert(rcdev, id); 1398c2ecf20Sopenharmony_ci if (err) 1408c2ecf20Sopenharmony_ci return err; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci udelay(1); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci return tegra_clk_rst_deassert(rcdev, id); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ciconst struct tegra_clk_periph_regs *get_reg_bank(int clkid) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci int reg_bank = clkid / 32; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (reg_bank < periph_banks) 1528c2ecf20Sopenharmony_ci return &periph_regs[reg_bank]; 1538c2ecf20Sopenharmony_ci else { 1548c2ecf20Sopenharmony_ci WARN_ON(1); 1558c2ecf20Sopenharmony_ci return NULL; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_civoid tegra_clk_set_pllp_out_cpu(bool enable) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci u32 val; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci val = readl_relaxed(clk_base + CLK_OUT_ENB_Y); 1648c2ecf20Sopenharmony_ci if (enable) 1658c2ecf20Sopenharmony_ci val |= CLK_ENB_PLLP_OUT_CPU; 1668c2ecf20Sopenharmony_ci else 1678c2ecf20Sopenharmony_ci val &= ~CLK_ENB_PLLP_OUT_CPU; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci writel_relaxed(val, clk_base + CLK_OUT_ENB_Y); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_civoid tegra_clk_periph_suspend(void) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci unsigned int i, idx; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci idx = 0; 1778c2ecf20Sopenharmony_ci for (i = 0; i < periph_banks; i++, idx++) 1788c2ecf20Sopenharmony_ci periph_state_ctx[idx] = 1798c2ecf20Sopenharmony_ci readl_relaxed(clk_base + periph_regs[i].enb_reg); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci for (i = 0; i < periph_banks; i++, idx++) 1828c2ecf20Sopenharmony_ci periph_state_ctx[idx] = 1838c2ecf20Sopenharmony_ci readl_relaxed(clk_base + periph_regs[i].rst_reg); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_civoid tegra_clk_periph_resume(void) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci unsigned int i, idx; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci idx = 0; 1918c2ecf20Sopenharmony_ci for (i = 0; i < periph_banks; i++, idx++) 1928c2ecf20Sopenharmony_ci writel_relaxed(periph_state_ctx[idx], 1938c2ecf20Sopenharmony_ci clk_base + periph_regs[i].enb_reg); 1948c2ecf20Sopenharmony_ci /* 1958c2ecf20Sopenharmony_ci * All non-boot peripherals will be in reset state on resume. 1968c2ecf20Sopenharmony_ci * Wait for 5us of reset propagation delay before de-asserting 1978c2ecf20Sopenharmony_ci * the peripherals based on the saved context. 1988c2ecf20Sopenharmony_ci */ 1998c2ecf20Sopenharmony_ci fence_udelay(5, clk_base); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci for (i = 0; i < periph_banks; i++, idx++) 2028c2ecf20Sopenharmony_ci writel_relaxed(periph_state_ctx[idx], 2038c2ecf20Sopenharmony_ci clk_base + periph_regs[i].rst_reg); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci fence_udelay(2, clk_base); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic int tegra_clk_periph_ctx_init(int banks) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci periph_state_ctx = kcalloc(2 * banks, sizeof(*periph_state_ctx), 2118c2ecf20Sopenharmony_ci GFP_KERNEL); 2128c2ecf20Sopenharmony_ci if (!periph_state_ctx) 2138c2ecf20Sopenharmony_ci return -ENOMEM; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return 0; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistruct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci clk_base = regs; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (WARN_ON(banks > ARRAY_SIZE(periph_regs))) 2238c2ecf20Sopenharmony_ci return NULL; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci periph_clk_enb_refcnt = kcalloc(32 * banks, 2268c2ecf20Sopenharmony_ci sizeof(*periph_clk_enb_refcnt), 2278c2ecf20Sopenharmony_ci GFP_KERNEL); 2288c2ecf20Sopenharmony_ci if (!periph_clk_enb_refcnt) 2298c2ecf20Sopenharmony_ci return NULL; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci periph_banks = banks; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci clks = kcalloc(num, sizeof(struct clk *), GFP_KERNEL); 2348c2ecf20Sopenharmony_ci if (!clks) { 2358c2ecf20Sopenharmony_ci kfree(periph_clk_enb_refcnt); 2368c2ecf20Sopenharmony_ci return NULL; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci clk_num = num; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PM_SLEEP)) { 2428c2ecf20Sopenharmony_ci if (tegra_clk_periph_ctx_init(banks)) { 2438c2ecf20Sopenharmony_ci kfree(periph_clk_enb_refcnt); 2448c2ecf20Sopenharmony_ci kfree(clks); 2458c2ecf20Sopenharmony_ci return NULL; 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci return clks; 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_civoid __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, 2538c2ecf20Sopenharmony_ci struct clk *clks[], int clk_max) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct clk *clk; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci for (; dup_list->clk_id < clk_max; dup_list++) { 2588c2ecf20Sopenharmony_ci clk = clks[dup_list->clk_id]; 2598c2ecf20Sopenharmony_ci dup_list->lookup.clk = clk; 2608c2ecf20Sopenharmony_ci clkdev_add(&dup_list->lookup); 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_civoid __init tegra_init_from_table(struct tegra_clk_init_table *tbl, 2658c2ecf20Sopenharmony_ci struct clk *clks[], int clk_max) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct clk *clk; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci for (; tbl->clk_id < clk_max; tbl++) { 2708c2ecf20Sopenharmony_ci clk = clks[tbl->clk_id]; 2718c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(clk)) { 2728c2ecf20Sopenharmony_ci pr_err("%s: invalid entry %ld in clks array for id %d\n", 2738c2ecf20Sopenharmony_ci __func__, PTR_ERR(clk), tbl->clk_id); 2748c2ecf20Sopenharmony_ci WARN_ON(1); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci continue; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (tbl->parent_id < clk_max) { 2808c2ecf20Sopenharmony_ci struct clk *parent = clks[tbl->parent_id]; 2818c2ecf20Sopenharmony_ci if (clk_set_parent(clk, parent)) { 2828c2ecf20Sopenharmony_ci pr_err("%s: Failed to set parent %s of %s\n", 2838c2ecf20Sopenharmony_ci __func__, __clk_get_name(parent), 2848c2ecf20Sopenharmony_ci __clk_get_name(clk)); 2858c2ecf20Sopenharmony_ci WARN_ON(1); 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (tbl->rate) 2908c2ecf20Sopenharmony_ci if (clk_set_rate(clk, tbl->rate)) { 2918c2ecf20Sopenharmony_ci pr_err("%s: Failed to set rate %lu of %s\n", 2928c2ecf20Sopenharmony_ci __func__, tbl->rate, 2938c2ecf20Sopenharmony_ci __clk_get_name(clk)); 2948c2ecf20Sopenharmony_ci WARN_ON(1); 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (tbl->state) 2988c2ecf20Sopenharmony_ci if (clk_prepare_enable(clk)) { 2998c2ecf20Sopenharmony_ci pr_err("%s: Failed to enable %s\n", __func__, 3008c2ecf20Sopenharmony_ci __clk_get_name(clk)); 3018c2ecf20Sopenharmony_ci WARN_ON(1); 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic const struct reset_control_ops rst_ops = { 3078c2ecf20Sopenharmony_ci .assert = tegra_clk_rst_assert, 3088c2ecf20Sopenharmony_ci .deassert = tegra_clk_rst_deassert, 3098c2ecf20Sopenharmony_ci .reset = tegra_clk_rst_reset, 3108c2ecf20Sopenharmony_ci}; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic struct reset_controller_dev rst_ctlr = { 3138c2ecf20Sopenharmony_ci .ops = &rst_ops, 3148c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3158c2ecf20Sopenharmony_ci .of_reset_n_cells = 1, 3168c2ecf20Sopenharmony_ci}; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_civoid __init tegra_add_of_provider(struct device_node *np, 3198c2ecf20Sopenharmony_ci void *clk_src_onecell_get) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci int i; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci for (i = 0; i < clk_num; i++) { 3248c2ecf20Sopenharmony_ci if (IS_ERR(clks[i])) { 3258c2ecf20Sopenharmony_ci pr_err 3268c2ecf20Sopenharmony_ci ("Tegra clk %d: register failed with %ld\n", 3278c2ecf20Sopenharmony_ci i, PTR_ERR(clks[i])); 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci if (!clks[i]) 3308c2ecf20Sopenharmony_ci clks[i] = ERR_PTR(-EINVAL); 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci clk_data.clks = clks; 3348c2ecf20Sopenharmony_ci clk_data.clk_num = clk_num; 3358c2ecf20Sopenharmony_ci of_clk_add_provider(np, clk_src_onecell_get, &clk_data); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci rst_ctlr.of_node = np; 3388c2ecf20Sopenharmony_ci rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset; 3398c2ecf20Sopenharmony_ci reset_controller_register(&rst_ctlr); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_civoid __init tegra_init_special_resets(unsigned int num, 3438c2ecf20Sopenharmony_ci int (*assert)(unsigned long), 3448c2ecf20Sopenharmony_ci int (*deassert)(unsigned long)) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci num_special_reset = num; 3478c2ecf20Sopenharmony_ci special_reset_assert = assert; 3488c2ecf20Sopenharmony_ci special_reset_deassert = deassert; 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_civoid __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci int i; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci for (i = 0; i < num; i++, dev_clks++) 3568c2ecf20Sopenharmony_ci clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id, 3578c2ecf20Sopenharmony_ci dev_clks->dev_id); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci for (i = 0; i < clk_num; i++) { 3608c2ecf20Sopenharmony_ci if (!IS_ERR_OR_NULL(clks[i])) 3618c2ecf20Sopenharmony_ci clk_register_clkdev(clks[i], __clk_get_name(clks[i]), 3628c2ecf20Sopenharmony_ci "tegra-clk-debug"); 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistruct clk ** __init tegra_lookup_dt_id(int clk_id, 3678c2ecf20Sopenharmony_ci struct tegra_clk *tegra_clk) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci if (tegra_clk[clk_id].present) 3708c2ecf20Sopenharmony_ci return &clks[tegra_clk[clk_id].dt_id]; 3718c2ecf20Sopenharmony_ci else 3728c2ecf20Sopenharmony_ci return NULL; 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_citegra_clk_apply_init_table_func tegra_clk_apply_init_table; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic int __init tegra_clocks_apply_init_table(void) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci if (!tegra_clk_apply_init_table) 3808c2ecf20Sopenharmony_ci return 0; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci tegra_clk_apply_init_table(); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci return 0; 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ciarch_initcall(tegra_clocks_apply_init_table); 387