18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (C) 2012 ST Microelectronics 38c2ecf20Sopenharmony_ci * Viresh Kumar <vireshk@kernel.org> 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public 68c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any 78c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * VCO-PLL clock implementation 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "clk-vco-pll: " fmt 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/io.h> 178c2ecf20Sopenharmony_ci#include <linux/err.h> 188c2ecf20Sopenharmony_ci#include "clk.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci * DOC: VCO-PLL clock 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * VCO and PLL rate are derived from following equations: 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * In normal mode 268c2ecf20Sopenharmony_ci * vco = (2 * M[15:8] * Fin)/N 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * In Dithered mode 298c2ecf20Sopenharmony_ci * vco = (2 * M[15:0] * Fin)/(256 * N) 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * pll_rate = pll/2^p 328c2ecf20Sopenharmony_ci * 338c2ecf20Sopenharmony_ci * vco and pll are very closely bound to each other, "vco needs to program: 348c2ecf20Sopenharmony_ci * mode, m & n" and "pll needs to program p", both share common enable/disable 358c2ecf20Sopenharmony_ci * logic. 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * clk_register_vco_pll() registers instances of both vco & pll. 388c2ecf20Sopenharmony_ci * CLK_SET_RATE_PARENT flag is forced for pll, as it will always pass its 398c2ecf20Sopenharmony_ci * set_rate to vco. A single rate table exists for both the clocks, which 408c2ecf20Sopenharmony_ci * configures m, n and p. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* PLL_CTR register masks */ 448c2ecf20Sopenharmony_ci#define PLL_MODE_NORMAL 0 458c2ecf20Sopenharmony_ci#define PLL_MODE_FRACTION 1 468c2ecf20Sopenharmony_ci#define PLL_MODE_DITH_DSM 2 478c2ecf20Sopenharmony_ci#define PLL_MODE_DITH_SSM 3 488c2ecf20Sopenharmony_ci#define PLL_MODE_MASK 3 498c2ecf20Sopenharmony_ci#define PLL_MODE_SHIFT 3 508c2ecf20Sopenharmony_ci#define PLL_ENABLE 2 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define PLL_LOCK_SHIFT 0 538c2ecf20Sopenharmony_ci#define PLL_LOCK_MASK 1 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* PLL FRQ register masks */ 568c2ecf20Sopenharmony_ci#define PLL_NORM_FDBK_M_MASK 0xFF 578c2ecf20Sopenharmony_ci#define PLL_NORM_FDBK_M_SHIFT 24 588c2ecf20Sopenharmony_ci#define PLL_DITH_FDBK_M_MASK 0xFFFF 598c2ecf20Sopenharmony_ci#define PLL_DITH_FDBK_M_SHIFT 16 608c2ecf20Sopenharmony_ci#define PLL_DIV_P_MASK 0x7 618c2ecf20Sopenharmony_ci#define PLL_DIV_P_SHIFT 8 628c2ecf20Sopenharmony_ci#define PLL_DIV_N_MASK 0xFF 638c2ecf20Sopenharmony_ci#define PLL_DIV_N_SHIFT 0 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define to_clk_vco(_hw) container_of(_hw, struct clk_vco, hw) 668c2ecf20Sopenharmony_ci#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Calculates pll clk rate for specific value of mode, m, n and p */ 698c2ecf20Sopenharmony_cistatic unsigned long pll_calc_rate(struct pll_rate_tbl *rtbl, 708c2ecf20Sopenharmony_ci unsigned long prate, int index, unsigned long *pll_rate) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci unsigned long rate = prate; 738c2ecf20Sopenharmony_ci unsigned int mode; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci mode = rtbl[index].mode ? 256 : 1; 768c2ecf20Sopenharmony_ci rate = (((2 * rate / 10000) * rtbl[index].m) / (mode * rtbl[index].n)); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (pll_rate) 798c2ecf20Sopenharmony_ci *pll_rate = (rate / (1 << rtbl[index].p)) * 10000; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return rate * 10000; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic long clk_pll_round_rate_index(struct clk_hw *hw, unsigned long drate, 858c2ecf20Sopenharmony_ci unsigned long *prate, int *index) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct clk_pll *pll = to_clk_pll(hw); 888c2ecf20Sopenharmony_ci unsigned long prev_rate, vco_prev_rate, rate = 0; 898c2ecf20Sopenharmony_ci unsigned long vco_parent_rate = 908c2ecf20Sopenharmony_ci clk_hw_get_rate(clk_hw_get_parent(clk_hw_get_parent(hw))); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if (!prate) { 938c2ecf20Sopenharmony_ci pr_err("%s: prate is must for pll clk\n", __func__); 948c2ecf20Sopenharmony_ci return -EINVAL; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci for (*index = 0; *index < pll->vco->rtbl_cnt; (*index)++) { 988c2ecf20Sopenharmony_ci prev_rate = rate; 998c2ecf20Sopenharmony_ci vco_prev_rate = *prate; 1008c2ecf20Sopenharmony_ci *prate = pll_calc_rate(pll->vco->rtbl, vco_parent_rate, *index, 1018c2ecf20Sopenharmony_ci &rate); 1028c2ecf20Sopenharmony_ci if (drate < rate) { 1038c2ecf20Sopenharmony_ci /* previous clock was best */ 1048c2ecf20Sopenharmony_ci if (*index) { 1058c2ecf20Sopenharmony_ci rate = prev_rate; 1068c2ecf20Sopenharmony_ci *prate = vco_prev_rate; 1078c2ecf20Sopenharmony_ci (*index)--; 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci break; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci return rate; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic long clk_pll_round_rate(struct clk_hw *hw, unsigned long drate, 1178c2ecf20Sopenharmony_ci unsigned long *prate) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci int unused; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci return clk_pll_round_rate_index(hw, drate, prate, &unused); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long 1258c2ecf20Sopenharmony_ci parent_rate) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct clk_pll *pll = to_clk_pll(hw); 1288c2ecf20Sopenharmony_ci unsigned long flags = 0; 1298c2ecf20Sopenharmony_ci unsigned int p; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (pll->vco->lock) 1328c2ecf20Sopenharmony_ci spin_lock_irqsave(pll->vco->lock, flags); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci p = readl_relaxed(pll->vco->cfg_reg); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (pll->vco->lock) 1378c2ecf20Sopenharmony_ci spin_unlock_irqrestore(pll->vco->lock, flags); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci p = (p >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci return parent_rate / (1 << p); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate, 1458c2ecf20Sopenharmony_ci unsigned long prate) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct clk_pll *pll = to_clk_pll(hw); 1488c2ecf20Sopenharmony_ci struct pll_rate_tbl *rtbl = pll->vco->rtbl; 1498c2ecf20Sopenharmony_ci unsigned long flags = 0, val; 1508c2ecf20Sopenharmony_ci int i = 0; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci clk_pll_round_rate_index(hw, drate, NULL, &i); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (pll->vco->lock) 1558c2ecf20Sopenharmony_ci spin_lock_irqsave(pll->vco->lock, flags); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci val = readl_relaxed(pll->vco->cfg_reg); 1588c2ecf20Sopenharmony_ci val &= ~(PLL_DIV_P_MASK << PLL_DIV_P_SHIFT); 1598c2ecf20Sopenharmony_ci val |= (rtbl[i].p & PLL_DIV_P_MASK) << PLL_DIV_P_SHIFT; 1608c2ecf20Sopenharmony_ci writel_relaxed(val, pll->vco->cfg_reg); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (pll->vco->lock) 1638c2ecf20Sopenharmony_ci spin_unlock_irqrestore(pll->vco->lock, flags); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci return 0; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic const struct clk_ops clk_pll_ops = { 1698c2ecf20Sopenharmony_ci .recalc_rate = clk_pll_recalc_rate, 1708c2ecf20Sopenharmony_ci .round_rate = clk_pll_round_rate, 1718c2ecf20Sopenharmony_ci .set_rate = clk_pll_set_rate, 1728c2ecf20Sopenharmony_ci}; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic inline unsigned long vco_calc_rate(struct clk_hw *hw, 1758c2ecf20Sopenharmony_ci unsigned long prate, int index) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci struct clk_vco *vco = to_clk_vco(hw); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return pll_calc_rate(vco->rtbl, prate, index, NULL); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic long clk_vco_round_rate(struct clk_hw *hw, unsigned long drate, 1838c2ecf20Sopenharmony_ci unsigned long *prate) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci struct clk_vco *vco = to_clk_vco(hw); 1868c2ecf20Sopenharmony_ci int unused; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci return clk_round_rate_index(hw, drate, *prate, vco_calc_rate, 1898c2ecf20Sopenharmony_ci vco->rtbl_cnt, &unused); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic unsigned long clk_vco_recalc_rate(struct clk_hw *hw, 1938c2ecf20Sopenharmony_ci unsigned long parent_rate) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci struct clk_vco *vco = to_clk_vco(hw); 1968c2ecf20Sopenharmony_ci unsigned long flags = 0; 1978c2ecf20Sopenharmony_ci unsigned int num = 2, den = 0, val, mode = 0; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (vco->lock) 2008c2ecf20Sopenharmony_ci spin_lock_irqsave(vco->lock, flags); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci mode = (readl_relaxed(vco->mode_reg) >> PLL_MODE_SHIFT) & PLL_MODE_MASK; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci val = readl_relaxed(vco->cfg_reg); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (vco->lock) 2078c2ecf20Sopenharmony_ci spin_unlock_irqrestore(vco->lock, flags); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci den = (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* calculate numerator & denominator */ 2128c2ecf20Sopenharmony_ci if (!mode) { 2138c2ecf20Sopenharmony_ci /* Normal mode */ 2148c2ecf20Sopenharmony_ci num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; 2158c2ecf20Sopenharmony_ci } else { 2168c2ecf20Sopenharmony_ci /* Dithered mode */ 2178c2ecf20Sopenharmony_ci num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; 2188c2ecf20Sopenharmony_ci den *= 256; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!den) { 2228c2ecf20Sopenharmony_ci WARN(1, "%s: denominator can't be zero\n", __func__); 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return (((parent_rate / 10000) * num) / den) * 10000; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci/* Configures new clock rate of vco */ 2308c2ecf20Sopenharmony_cistatic int clk_vco_set_rate(struct clk_hw *hw, unsigned long drate, 2318c2ecf20Sopenharmony_ci unsigned long prate) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci struct clk_vco *vco = to_clk_vco(hw); 2348c2ecf20Sopenharmony_ci struct pll_rate_tbl *rtbl = vco->rtbl; 2358c2ecf20Sopenharmony_ci unsigned long flags = 0, val; 2368c2ecf20Sopenharmony_ci int i; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci clk_round_rate_index(hw, drate, prate, vco_calc_rate, vco->rtbl_cnt, 2398c2ecf20Sopenharmony_ci &i); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (vco->lock) 2428c2ecf20Sopenharmony_ci spin_lock_irqsave(vco->lock, flags); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci val = readl_relaxed(vco->mode_reg); 2458c2ecf20Sopenharmony_ci val &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT); 2468c2ecf20Sopenharmony_ci val |= (rtbl[i].mode & PLL_MODE_MASK) << PLL_MODE_SHIFT; 2478c2ecf20Sopenharmony_ci writel_relaxed(val, vco->mode_reg); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci val = readl_relaxed(vco->cfg_reg); 2508c2ecf20Sopenharmony_ci val &= ~(PLL_DIV_N_MASK << PLL_DIV_N_SHIFT); 2518c2ecf20Sopenharmony_ci val |= (rtbl[i].n & PLL_DIV_N_MASK) << PLL_DIV_N_SHIFT; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci val &= ~(PLL_DITH_FDBK_M_MASK << PLL_DITH_FDBK_M_SHIFT); 2548c2ecf20Sopenharmony_ci if (rtbl[i].mode) 2558c2ecf20Sopenharmony_ci val |= (rtbl[i].m & PLL_DITH_FDBK_M_MASK) << 2568c2ecf20Sopenharmony_ci PLL_DITH_FDBK_M_SHIFT; 2578c2ecf20Sopenharmony_ci else 2588c2ecf20Sopenharmony_ci val |= (rtbl[i].m & PLL_NORM_FDBK_M_MASK) << 2598c2ecf20Sopenharmony_ci PLL_NORM_FDBK_M_SHIFT; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci writel_relaxed(val, vco->cfg_reg); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (vco->lock) 2648c2ecf20Sopenharmony_ci spin_unlock_irqrestore(vco->lock, flags); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci return 0; 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic const struct clk_ops clk_vco_ops = { 2708c2ecf20Sopenharmony_ci .recalc_rate = clk_vco_recalc_rate, 2718c2ecf20Sopenharmony_ci .round_rate = clk_vco_round_rate, 2728c2ecf20Sopenharmony_ci .set_rate = clk_vco_set_rate, 2738c2ecf20Sopenharmony_ci}; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistruct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name, 2768c2ecf20Sopenharmony_ci const char *vco_gate_name, const char *parent_name, 2778c2ecf20Sopenharmony_ci unsigned long flags, void __iomem *mode_reg, void __iomem 2788c2ecf20Sopenharmony_ci *cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt, 2798c2ecf20Sopenharmony_ci spinlock_t *lock, struct clk **pll_clk, 2808c2ecf20Sopenharmony_ci struct clk **vco_gate_clk) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci struct clk_vco *vco; 2838c2ecf20Sopenharmony_ci struct clk_pll *pll; 2848c2ecf20Sopenharmony_ci struct clk *vco_clk, *tpll_clk, *tvco_gate_clk; 2858c2ecf20Sopenharmony_ci struct clk_init_data vco_init, pll_init; 2868c2ecf20Sopenharmony_ci const char **vco_parent_name; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (!vco_name || !pll_name || !parent_name || !mode_reg || !cfg_reg || 2898c2ecf20Sopenharmony_ci !rtbl || !rtbl_cnt) { 2908c2ecf20Sopenharmony_ci pr_err("Invalid arguments passed"); 2918c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci vco = kzalloc(sizeof(*vco), GFP_KERNEL); 2958c2ecf20Sopenharmony_ci if (!vco) 2968c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci pll = kzalloc(sizeof(*pll), GFP_KERNEL); 2998c2ecf20Sopenharmony_ci if (!pll) 3008c2ecf20Sopenharmony_ci goto free_vco; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* struct clk_vco assignments */ 3038c2ecf20Sopenharmony_ci vco->mode_reg = mode_reg; 3048c2ecf20Sopenharmony_ci vco->cfg_reg = cfg_reg; 3058c2ecf20Sopenharmony_ci vco->rtbl = rtbl; 3068c2ecf20Sopenharmony_ci vco->rtbl_cnt = rtbl_cnt; 3078c2ecf20Sopenharmony_ci vco->lock = lock; 3088c2ecf20Sopenharmony_ci vco->hw.init = &vco_init; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci pll->vco = vco; 3118c2ecf20Sopenharmony_ci pll->hw.init = &pll_init; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci if (vco_gate_name) { 3148c2ecf20Sopenharmony_ci tvco_gate_clk = clk_register_gate(NULL, vco_gate_name, 3158c2ecf20Sopenharmony_ci parent_name, 0, mode_reg, PLL_ENABLE, 0, lock); 3168c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(tvco_gate_clk)) 3178c2ecf20Sopenharmony_ci goto free_pll; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci if (vco_gate_clk) 3208c2ecf20Sopenharmony_ci *vco_gate_clk = tvco_gate_clk; 3218c2ecf20Sopenharmony_ci vco_parent_name = &vco_gate_name; 3228c2ecf20Sopenharmony_ci } else { 3238c2ecf20Sopenharmony_ci vco_parent_name = &parent_name; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci vco_init.name = vco_name; 3278c2ecf20Sopenharmony_ci vco_init.ops = &clk_vco_ops; 3288c2ecf20Sopenharmony_ci vco_init.flags = flags; 3298c2ecf20Sopenharmony_ci vco_init.parent_names = vco_parent_name; 3308c2ecf20Sopenharmony_ci vco_init.num_parents = 1; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci pll_init.name = pll_name; 3338c2ecf20Sopenharmony_ci pll_init.ops = &clk_pll_ops; 3348c2ecf20Sopenharmony_ci pll_init.flags = CLK_SET_RATE_PARENT; 3358c2ecf20Sopenharmony_ci pll_init.parent_names = &vco_name; 3368c2ecf20Sopenharmony_ci pll_init.num_parents = 1; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci vco_clk = clk_register(NULL, &vco->hw); 3398c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(vco_clk)) 3408c2ecf20Sopenharmony_ci goto free_pll; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci tpll_clk = clk_register(NULL, &pll->hw); 3438c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(tpll_clk)) 3448c2ecf20Sopenharmony_ci goto free_pll; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (pll_clk) 3478c2ecf20Sopenharmony_ci *pll_clk = tpll_clk; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci return vco_clk; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cifree_pll: 3528c2ecf20Sopenharmony_ci kfree(pll); 3538c2ecf20Sopenharmony_cifree_vco: 3548c2ecf20Sopenharmony_ci kfree(vco); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci pr_err("Failed to register vco pll clock\n"); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3598c2ecf20Sopenharmony_ci} 360