1b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot/* 2b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. 3b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * 4b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * Permission is hereby granted, free of charge, to any person obtaining a 5b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * copy of this software and associated documentation files (the "Software"), 6b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * to deal in the Software without restriction, including without limitation 7b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * and/or sell copies of the Software, and to permit persons to whom the 9b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * Software is furnished to do so, subject to the following conditions: 10b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * 11b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * The above copyright notice and this permission notice shall be included in 12b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * all copies or substantial portions of the Software. 13b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * 14b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * DEALINGS IN THE SOFTWARE. 21b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * 22b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * Shamelessly ripped off from ChromeOS's gk20a/clk_pllg.c 23b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot * 24b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot */ 25b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 26b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define MHZ (1000 * 1000) 27b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 28b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define MASK(w) ((1 << w) - 1) 29b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 30b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define SYS_GPCPLL_CFG_BASE 0x00137000 31b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC_BCASE_GPCPLL_CFG_BASE 0x00132800 32b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 33b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG (SYS_GPCPLL_CFG_BASE + 0) 34b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG_ENABLE BIT(0) 35b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG_IDDQ BIT(1) 36b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG_LOCK_DET_OFF BIT(4) 37b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG_LOCK BIT(17) 38b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 39b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_COEFF (SYS_GPCPLL_CFG_BASE + 4) 40b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_COEFF_M_SHIFT 0 41b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_COEFF_M_WIDTH 8 42b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_COEFF_N_SHIFT 8 43b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_COEFF_N_WIDTH 8 44b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_COEFF_P_SHIFT 16 45b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_COEFF_P_WIDTH 6 46b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 47b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG2 (SYS_GPCPLL_CFG_BASE + 0xc) 48b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG2_SETUP2_SHIFT 16 49b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG2_PLL_STEPA_SHIFT 24 50b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 51b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG3 (SYS_GPCPLL_CFG_BASE + 0x18) 52b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_CFG3_PLL_STEPB_SHIFT 16 53b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 54b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_NDIV_SLOWDOWN (SYS_GPCPLL_CFG_BASE + 0x1c) 55b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_NDIV_SLOWDOWN_NDIV_LO_SHIFT 0 56b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_NDIV_SLOWDOWN_NDIV_MID_SHIFT 8 57b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_NDIV_SLOWDOWN_STEP_SIZE_LO2MID_SHIFT 16 58b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT 22 59b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT 31 60b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 61b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define SEL_VCO (SYS_GPCPLL_CFG_BASE + 0x100) 62b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define SEL_VCO_GPC2CLK_OUT_SHIFT 0 63b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 64b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT (SYS_GPCPLL_CFG_BASE + 0x250) 65b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_SDIV14_INDIV4_WIDTH 1 66b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_SDIV14_INDIV4_SHIFT 31 67b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_SDIV14_INDIV4_MODE 1 68b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_VCODIV_WIDTH 6 69b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_VCODIV_SHIFT 8 70b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_VCODIV1 0 71b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_VCODIV_MASK (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << \ 72b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot GPC2CLK_OUT_VCODIV_SHIFT) 73b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_BYPDIV_WIDTH 6 74b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_BYPDIV_SHIFT 0 75b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_BYPDIV31 0x3c 76b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_INIT_MASK ((MASK(GPC2CLK_OUT_SDIV14_INDIV4_WIDTH) << \ 77b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot GPC2CLK_OUT_SDIV14_INDIV4_SHIFT)\ 78b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot | (MASK(GPC2CLK_OUT_VCODIV_WIDTH) << GPC2CLK_OUT_VCODIV_SHIFT)\ 79b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot | (MASK(GPC2CLK_OUT_BYPDIV_WIDTH) << GPC2CLK_OUT_BYPDIV_SHIFT)) 80b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC2CLK_OUT_INIT_VAL ((GPC2CLK_OUT_SDIV14_INDIV4_MODE << \ 81b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot GPC2CLK_OUT_SDIV14_INDIV4_SHIFT) \ 82b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot | (GPC2CLK_OUT_VCODIV1 << GPC2CLK_OUT_VCODIV_SHIFT) \ 83b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot | (GPC2CLK_OUT_BYPDIV31 << GPC2CLK_OUT_BYPDIV_SHIFT)) 84b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 85b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG (GPC_BCASE_GPCPLL_CFG_BASE + 0xa0) 86b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT 24 87b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK \ 88b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot (0x1 << GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT) 89b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 90b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#include <subdev/clock.h> 91b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#include <subdev/timer.h> 92b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 93b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#ifdef __KERNEL__ 94b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#include <nouveau_platform.h> 95b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#endif 96b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 97b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic const u8 pl_to_div[] = { 98b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot/* PL: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ 99b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32, 100b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot}; 101b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 102b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot/* All frequencies in Mhz */ 103b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstruct gk20a_clk_pllg_params { 104b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 min_vco, max_vco; 105b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 min_u, max_u; 106b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 min_m, max_m; 107b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 min_n, max_n; 108b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 min_pl, max_pl; 109b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot}; 110b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 111b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic const struct gk20a_clk_pllg_params gk20a_pllg_params = { 112b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .min_vco = 1000, .max_vco = 1700, 113b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .min_u = 12, .max_u = 38, 114b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .min_m = 1, .max_m = 255, 115b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .min_n = 8, .max_n = 255, 116b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .min_pl = 1, .max_pl = 32, 117b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot}; 118b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 119b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstruct gk20a_clock_priv { 120b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct nouveau_clock base; 121b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot const struct gk20a_clk_pllg_params *params; 122b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 m, n, pl; 123b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 parent_rate; 124b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot}; 125b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define to_gk20a_clock(base) container_of(base, struct gk20a_clock_priv, base) 126b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 127b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic void 128b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_pllg_read_mnp(struct gk20a_clock_priv *priv) 129b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 130b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 val; 131b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 132b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_COEFF); 133b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->m = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH); 134b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->n = (val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH); 135b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->pl = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH); 136b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 137b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 138b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic u32 139b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_pllg_calc_rate(struct gk20a_clock_priv *priv) 140b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 141b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 rate; 142b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 divider; 143b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 144b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot rate = priv->parent_rate * priv->n; 145b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot divider = priv->m * pl_to_div[priv->pl]; 146b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot do_div(rate, divider); 147b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 148b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return rate / 2; 149b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 150b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 151b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 152b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_pllg_calc_mnp(struct gk20a_clock_priv *priv, unsigned long rate) 153b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 154b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 target_clk_f, ref_clk_f, target_freq; 155b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 min_vco_f, max_vco_f; 156b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 low_pl, high_pl, best_pl; 157b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 target_vco_f, vco_f; 158b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 best_m, best_n; 159b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 u_f; 160b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 m, n, n2; 161b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 delta, lwv, best_delta = ~0; 162b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 pl; 163b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 164b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot target_clk_f = rate * 2 / MHZ; 165b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot ref_clk_f = priv->parent_rate / MHZ; 166b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 167b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot max_vco_f = priv->params->max_vco; 168b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot min_vco_f = priv->params->min_vco; 169b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot best_m = priv->params->max_m; 170b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot best_n = priv->params->min_n; 171b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot best_pl = priv->params->min_pl; 172b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 173b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot target_vco_f = target_clk_f + target_clk_f / 50; 174b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (max_vco_f < target_vco_f) 175b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot max_vco_f = target_vco_f; 176b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 177b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* min_pl <= high_pl <= max_pl */ 178b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot high_pl = (max_vco_f + target_vco_f - 1) / target_vco_f; 179b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot high_pl = min(high_pl, priv->params->max_pl); 180b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot high_pl = max(high_pl, priv->params->min_pl); 181b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 182b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* min_pl <= low_pl <= max_pl */ 183b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot low_pl = min_vco_f / target_vco_f; 184b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot low_pl = min(low_pl, priv->params->max_pl); 185b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot low_pl = max(low_pl, priv->params->min_pl); 186b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 187b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* Find Indices of high_pl and low_pl */ 188b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) { 189b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (pl_to_div[pl] >= low_pl) { 190b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot low_pl = pl; 191b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot break; 192b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 193b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 194b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot for (pl = 0; pl < ARRAY_SIZE(pl_to_div) - 1; pl++) { 195b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (pl_to_div[pl] >= high_pl) { 196b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot high_pl = pl; 197b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot break; 198b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 199b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 200b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 201b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_debug(priv, "low_PL %d(div%d), high_PL %d(div%d)", low_pl, 202b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot pl_to_div[low_pl], high_pl, pl_to_div[high_pl]); 203b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 204b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* Select lowest possible VCO */ 205b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot for (pl = low_pl; pl <= high_pl; pl++) { 206b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot target_vco_f = target_clk_f * pl_to_div[pl]; 207b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot for (m = priv->params->min_m; m <= priv->params->max_m; m++) { 208b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u_f = ref_clk_f / m; 209b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 210b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (u_f < priv->params->min_u) 211b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot break; 212b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (u_f > priv->params->max_u) 213b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot continue; 214b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 215b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot n = (target_vco_f * m) / ref_clk_f; 216b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot n2 = ((target_vco_f * m) + (ref_clk_f - 1)) / ref_clk_f; 217b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 218b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (n > priv->params->max_n) 219b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot break; 220b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 221b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot for (; n <= n2; n++) { 222b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (n < priv->params->min_n) 223b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot continue; 224b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (n > priv->params->max_n) 225b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot break; 226b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 227b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot vco_f = ref_clk_f * n / m; 228b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 229b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (vco_f >= min_vco_f && vco_f <= max_vco_f) { 230b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot lwv = (vco_f + (pl_to_div[pl] / 2)) 231b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot / pl_to_div[pl]; 232b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot delta = abs(lwv - target_clk_f); 233b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 234b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (delta < best_delta) { 235b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot best_delta = delta; 236b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot best_m = m; 237b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot best_n = n; 238b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot best_pl = pl; 239b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 240b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (best_delta == 0) 241b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot goto found_match; 242b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 243b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 244b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 245b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 246b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 247b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 248b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotfound_match: 249b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot WARN_ON(best_delta == ~0); 250b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 251b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (best_delta != 0) 252b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_debug(priv, "no best match for target @ %dMHz on gpc_pll", 253b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot target_clk_f); 254b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 255b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->m = best_m; 256b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->n = best_n; 257b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->pl = best_pl; 258b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 259b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot target_freq = gk20a_pllg_calc_rate(priv) / MHZ; 260b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 261b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_debug(priv, "actual target freq %d MHz, M %d, N %d, PL %d(div%d)\n", 262b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot target_freq, priv->m, priv->n, priv->pl, pl_to_div[priv->pl]); 263b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 264b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return 0; 265b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 266b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 267b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 268b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_pllg_slide(struct gk20a_clock_priv *priv, u32 n) 269b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 270b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 val; 271b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot int ramp_timeout; 272b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 273b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* get old coefficients */ 274b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_COEFF); 275b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* do nothing if NDIV is the same */ 276b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (n == ((val >> GPCPLL_COEFF_N_SHIFT) & MASK(GPCPLL_COEFF_N_WIDTH))) 277b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return 0; 278b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 279b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* setup */ 280b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPCPLL_CFG2, 0xff << GPCPLL_CFG2_PLL_STEPA_SHIFT, 281b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 0x2b << GPCPLL_CFG2_PLL_STEPA_SHIFT); 282b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPCPLL_CFG3, 0xff << GPCPLL_CFG3_PLL_STEPB_SHIFT, 283b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 0xb << GPCPLL_CFG3_PLL_STEPB_SHIFT); 284b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 285b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* pll slowdown mode */ 286b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPCPLL_NDIV_SLOWDOWN, 287b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT), 288b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT)); 289b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 290b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* new ndiv ready for ramp */ 291b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_COEFF); 292b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val &= ~(MASK(GPCPLL_COEFF_N_WIDTH) << GPCPLL_COEFF_N_SHIFT); 293b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val |= (n & MASK(GPCPLL_COEFF_N_WIDTH)) << GPCPLL_COEFF_N_SHIFT; 294b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot udelay(1); 295b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_wr32(priv, GPCPLL_COEFF, val); 296b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 297b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* dynamic ramp to new ndiv */ 298b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN); 299b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val |= 0x1 << GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT; 300b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot udelay(1); 301b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_wr32(priv, GPCPLL_NDIV_SLOWDOWN, val); 302b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 303b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot for (ramp_timeout = 500; ramp_timeout > 0; ramp_timeout--) { 304b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot udelay(1); 305b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPC_BCAST_NDIV_SLOWDOWN_DEBUG); 306b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (val & GPC_BCAST_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_MASK) 307b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot break; 308b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 309b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 310b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* exit slowdown mode */ 311b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPCPLL_NDIV_SLOWDOWN, 312b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot BIT(GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT) | 313b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot BIT(GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT), 0); 314b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_rd32(priv, GPCPLL_NDIV_SLOWDOWN); 315b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 316b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (ramp_timeout <= 0) { 317b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_error(priv, "gpcpll dynamic ramp timeout\n"); 318b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return -ETIMEDOUT; 319b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 320b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 321b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return 0; 322b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 323b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 324b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic void 325b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot_gk20a_pllg_enable(struct gk20a_clock_priv *priv) 326b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 327b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, GPCPLL_CFG_ENABLE); 328b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_rd32(priv, GPCPLL_CFG); 329b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 330b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 331b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic void 332b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot_gk20a_pllg_disable(struct gk20a_clock_priv *priv) 333b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 334b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPCPLL_CFG, GPCPLL_CFG_ENABLE, 0); 335b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_rd32(priv, GPCPLL_CFG); 336b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 337b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 338b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 339b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot_gk20a_pllg_program_mnp(struct gk20a_clock_priv *priv, bool allow_slide) 340b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 341b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 val, cfg; 342b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 m_old, pl_old, n_lo; 343b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 344b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* get old coefficients */ 345b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_COEFF); 346b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot m_old = (val >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH); 347b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot pl_old = (val >> GPCPLL_COEFF_P_SHIFT) & MASK(GPCPLL_COEFF_P_WIDTH); 348b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 349b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* do NDIV slide if there is no change in M and PL */ 350b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot cfg = nv_rd32(priv, GPCPLL_CFG); 351b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (allow_slide && priv->m == m_old && priv->pl == pl_old && 352b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot (cfg & GPCPLL_CFG_ENABLE)) { 353b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return gk20a_pllg_slide(priv, priv->n); 354b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 355b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 356b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* slide down to NDIV_LO */ 357b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot n_lo = DIV_ROUND_UP(m_old * priv->params->min_vco, 358b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->parent_rate / MHZ); 359b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (allow_slide && (cfg & GPCPLL_CFG_ENABLE)) { 360b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot int ret = gk20a_pllg_slide(priv, n_lo); 361b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 362b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (ret) 363b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return ret; 364b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 365b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 366b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* split FO-to-bypass jump in halfs by setting out divider 1:2 */ 367b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_VCODIV_MASK, 368b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 0x2 << GPC2CLK_OUT_VCODIV_SHIFT); 369b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 370b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* put PLL in bypass before programming it */ 371b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, SEL_VCO); 372b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val &= ~(BIT(SEL_VCO_GPC2CLK_OUT_SHIFT)); 373b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot udelay(2); 374b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_wr32(priv, SEL_VCO, val); 375b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 376b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* get out from IDDQ */ 377b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_CFG); 378b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (val & GPCPLL_CFG_IDDQ) { 379b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val &= ~GPCPLL_CFG_IDDQ; 380b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_wr32(priv, GPCPLL_CFG, val); 381b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_rd32(priv, GPCPLL_CFG); 382b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot udelay(2); 383b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 384b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 385b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot _gk20a_pllg_disable(priv); 386b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 387b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_debug(priv, "%s: m=%d n=%d pl=%d\n", __func__, priv->m, priv->n, 388b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->pl); 389b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 390b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot n_lo = DIV_ROUND_UP(priv->m * priv->params->min_vco, 391b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->parent_rate / MHZ); 392b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = priv->m << GPCPLL_COEFF_M_SHIFT; 393b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val |= (allow_slide ? n_lo : priv->n) << GPCPLL_COEFF_N_SHIFT; 394b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val |= priv->pl << GPCPLL_COEFF_P_SHIFT; 395b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_wr32(priv, GPCPLL_COEFF, val); 396b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 397b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot _gk20a_pllg_enable(priv); 398b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 399b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_CFG); 400b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (val & GPCPLL_CFG_LOCK_DET_OFF) { 401b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val &= ~GPCPLL_CFG_LOCK_DET_OFF; 402b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_wr32(priv, GPCPLL_CFG, val); 403b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 404b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 405b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (!nouveau_timer_wait_eq(priv, 300000, GPCPLL_CFG, GPCPLL_CFG_LOCK, 406b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot GPCPLL_CFG_LOCK)) { 407b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_error(priv, "%s: timeout waiting for pllg lock\n", __func__); 408b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return -ETIMEDOUT; 409b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 410b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 411b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* switch to VCO mode */ 412b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, SEL_VCO, 0, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT)); 413b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 414b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* restore out divider 1:1 */ 415b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPC2CLK_OUT); 416b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val &= ~GPC2CLK_OUT_VCODIV_MASK; 417b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot udelay(2); 418b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_wr32(priv, GPC2CLK_OUT, val); 419b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 420b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* slide up to new NDIV */ 421b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return allow_slide ? gk20a_pllg_slide(priv, priv->n) : 0; 422b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 423b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 424b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 425b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_pllg_program_mnp(struct gk20a_clock_priv *priv) 426b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 427b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot int err; 428b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 429b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot err = _gk20a_pllg_program_mnp(priv, true); 430b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (err) 431b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot err = _gk20a_pllg_program_mnp(priv, false); 432b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 433b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return err; 434b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 435b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 436b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic void 437b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_pllg_disable(struct gk20a_clock_priv *priv) 438b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 439b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 val; 440b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 441b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* slide to VCO min */ 442b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot val = nv_rd32(priv, GPCPLL_CFG); 443b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (val & GPCPLL_CFG_ENABLE) { 444b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot u32 coeff, m, n_lo; 445b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 446b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot coeff = nv_rd32(priv, GPCPLL_COEFF); 447b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot m = (coeff >> GPCPLL_COEFF_M_SHIFT) & MASK(GPCPLL_COEFF_M_WIDTH); 448b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot n_lo = DIV_ROUND_UP(m * priv->params->min_vco, 449b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->parent_rate / MHZ); 450b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot gk20a_pllg_slide(priv, n_lo); 451b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 452b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 453b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* put PLL in bypass before disabling it */ 454b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, SEL_VCO, BIT(SEL_VCO_GPC2CLK_OUT_SHIFT), 0); 455b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 456b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot _gk20a_pllg_disable(priv); 457b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 458b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 459b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot#define GK20A_CLK_GPC_MDIV 1000 460b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 461b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic struct nouveau_clocks 462b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_domains[] = { 463b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { nv_clk_src_crystal, 0xff }, 464b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV }, 465b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { nv_clk_src_max } 466b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot}; 467b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 468b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic struct nouveau_pstate 469b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_pstates[] = { 470b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 471b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 472b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 72000, 473b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 474b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 475b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 476b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 477b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 108000, 478b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 479b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 480b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 481b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 482b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 180000, 483b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 484b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 485b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 486b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 487b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 252000, 488b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 489b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 490b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 491b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 492b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 324000, 493b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 494b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 495b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 496b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 497b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 396000, 498b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 499b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 500b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 501b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 502b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 468000, 503b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 504b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 505b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 506b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 507b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 540000, 508b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 509b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 510b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 511b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 512b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 612000, 513b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 514b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 515b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 516b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 517b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 648000, 518b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 519b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 520b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 521b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 522b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 684000, 523b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 524b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 525b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 526b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 527b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 708000, 528b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 529b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 530b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 531b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 532b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 756000, 533b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 534b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 535b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 536b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 537b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 804000, 538b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 539b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 540b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot { 541b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .base = { 542b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .domain[nv_clk_src_gpc] = 852000, 543b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 544b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 545b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot}; 546b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 547b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 548b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_read(struct nouveau_clock *clk, enum nv_clk_src src) 549b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 550b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct gk20a_clock_priv *priv = (void *)clk; 551b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 552b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot switch (src) { 553b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot case nv_clk_src_crystal: 554b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return nv_device(clk)->crystal; 555b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot case nv_clk_src_gpc: 556b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot gk20a_pllg_read_mnp(priv); 557b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return gk20a_pllg_calc_rate(priv) / GK20A_CLK_GPC_MDIV; 558b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot default: 559b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_error(clk, "invalid clock source %d\n", src); 560b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return -EINVAL; 561b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 562b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 563b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 564b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 565b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_calc(struct nouveau_clock *clk, struct nouveau_cstate *cstate) 566b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 567b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct gk20a_clock_priv *priv = (void *)clk; 568b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 569b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return gk20a_pllg_calc_mnp(priv, cstate->domain[nv_clk_src_gpc] * 570b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot GK20A_CLK_GPC_MDIV); 571b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 572b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 573b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 574b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_prog(struct nouveau_clock *clk) 575b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 576b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct gk20a_clock_priv *priv = (void *)clk; 577b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 578b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return gk20a_pllg_program_mnp(priv); 579b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 580b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 581b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic void 582b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_tidy(struct nouveau_clock *clk) 583b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 584b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 585b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 586b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 587b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_fini(struct nouveau_object *object, bool suspend) 588b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 589b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct gk20a_clock_priv *priv = (void *)object; 590b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot int ret; 591b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 592b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot ret = nouveau_clock_fini(&priv->base, false); 593b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 594b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot gk20a_pllg_disable(priv); 595b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 596b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return ret; 597b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 598b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 599b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 600b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_init(struct nouveau_object *object) 601b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 602b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct gk20a_clock_priv *priv = (void *)object; 603b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot int ret; 604b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 605b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_mask(priv, GPC2CLK_OUT, GPC2CLK_OUT_INIT_MASK, GPC2CLK_OUT_INIT_VAL); 606b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 607b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot ret = nouveau_clock_init(&priv->base); 608b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (ret) 609b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return ret; 610b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 611b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot ret = gk20a_clock_prog(&priv->base); 612b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (ret) { 613b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_error(priv, "cannot initialize clock\n"); 614b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return ret; 615b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 616b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 617b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return 0; 618b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 619b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 620b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstatic int 621b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 622b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct nouveau_oclass *oclass, void *data, u32 size, 623b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct nouveau_object **pobject) 624b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot{ 625b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct gk20a_clock_priv *priv; 626b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot struct nouveau_platform_device *plat; 627b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot int ret; 628b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot int i; 629b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 630b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot /* Finish initializing the pstates */ 631b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot for (i = 0; i < ARRAY_SIZE(gk20a_pstates); i++) { 632b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot INIT_LIST_HEAD(&gk20a_pstates[i].list); 633b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot gk20a_pstates[i].pstate = i + 1; 634b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot } 635b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 636b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot ret = nouveau_clock_create(parent, engine, oclass, gk20a_domains, 637b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot gk20a_pstates, ARRAY_SIZE(gk20a_pstates), true, &priv); 638b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot *pobject = nv_object(priv); 639b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot if (ret) 640b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return ret; 641b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 642b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->params = &gk20a_pllg_params; 643b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 644b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot plat = nv_device_to_platform(nv_device(parent)); 645b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->parent_rate = clk_get_rate(plat->gpu->clk); 646b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot nv_info(priv, "parent clock rate: %d Mhz\n", priv->parent_rate / MHZ); 647b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 648b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->base.read = gk20a_clock_read; 649b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->base.calc = gk20a_clock_calc; 650b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->base.prog = gk20a_clock_prog; 651b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot priv->base.tidy = gk20a_clock_tidy; 652b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 653b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot return 0; 654b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot} 655b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot 656b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotstruct nouveau_oclass 657b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbotgk20a_clock_oclass = { 658b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .handle = NV_SUBDEV(CLOCK, 0xea), 659b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .ofuncs = &(struct nouveau_ofuncs) { 660b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .ctor = gk20a_clock_ctor, 661b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .dtor = _nouveau_subdev_dtor, 662b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .init = gk20a_clock_init, 663b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot .fini = gk20a_clock_fini, 664b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot }, 665b13a0a9e2922cbfbf7b400f4f0fd0acd19f941dfAlexandre Courbot}; 666