1 /* 2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 23 #include <subdev/clk.h> 24 #include <core/device.h> 25 26 #include "priv.h" 27 #include "gk20a.h" 28 29 #define KHZ (1000) 30 #define MHZ (KHZ * 1000) 31 32 #define MASK(w) ((1 << w) - 1) 33 34 #define BYPASSCTRL_SYS (SYS_GPCPLL_CFG_BASE + 0x340) 35 #define BYPASSCTRL_SYS_GPCPLL_SHIFT 0 36 #define BYPASSCTRL_SYS_GPCPLL_WIDTH 1 37 38 static u32 pl_to_div(u32 pl) 39 { 40 return pl; 41 } 42 43 static u32 div_to_pl(u32 div) 44 { 45 return div; 46 } 47 48 static const struct gk20a_clk_pllg_params gm20b_pllg_params = { 49 .min_vco = 1300000, .max_vco = 2600000, 50 .min_u = 12000, .max_u = 38400, 51 .min_m = 1, .max_m = 255, 52 .min_n = 8, .max_n = 255, 53 .min_pl = 1, .max_pl = 31, 54 }; 55 56 static struct nvkm_pstate 57 gm20b_pstates[] = { 58 { 59 .base = { 60 .domain[nv_clk_src_gpc] = 76800, 61 .voltage = 0, 62 }, 63 }, 64 { 65 .base = { 66 .domain[nv_clk_src_gpc] = 153600, 67 .voltage = 1, 68 }, 69 }, 70 { 71 .base = { 72 .domain[nv_clk_src_gpc] = 230400, 73 .voltage = 2, 74 }, 75 }, 76 { 77 .base = { 78 .domain[nv_clk_src_gpc] = 307200, 79 .voltage = 3, 80 }, 81 }, 82 { 83 .base = { 84 .domain[nv_clk_src_gpc] = 384000, 85 .voltage = 4, 86 }, 87 }, 88 { 89 .base = { 90 .domain[nv_clk_src_gpc] = 460800, 91 .voltage = 5, 92 }, 93 }, 94 { 95 .base = { 96 .domain[nv_clk_src_gpc] = 537600, 97 .voltage = 6, 98 }, 99 }, 100 { 101 .base = { 102 .domain[nv_clk_src_gpc] = 614400, 103 .voltage = 7, 104 }, 105 }, 106 { 107 .base = { 108 .domain[nv_clk_src_gpc] = 691200, 109 .voltage = 8, 110 }, 111 }, 112 { 113 .base = { 114 .domain[nv_clk_src_gpc] = 768000, 115 .voltage = 9, 116 }, 117 }, 118 { 119 .base = { 120 .domain[nv_clk_src_gpc] = 844800, 121 .voltage = 10, 122 }, 123 }, 124 { 125 .base = { 126 .domain[nv_clk_src_gpc] = 921600, 127 .voltage = 11, 128 }, 129 }, 130 { 131 .base = { 132 .domain[nv_clk_src_gpc] = 998400, 133 .voltage = 12, 134 }, 135 }, 136 137 }; 138 139 static int 140 gm20b_clk_init(struct nvkm_clk *base) 141 { 142 struct gk20a_clk *clk = gk20a_clk(base); 143 struct nvkm_subdev *subdev = &clk->base.subdev; 144 struct nvkm_device *device = subdev->device; 145 int ret; 146 147 /* Set the global bypass control to VCO */ 148 nvkm_mask(device, BYPASSCTRL_SYS, 149 MASK(BYPASSCTRL_SYS_GPCPLL_WIDTH) << BYPASSCTRL_SYS_GPCPLL_SHIFT, 150 0); 151 152 /* Start with lowest frequency */ 153 base->func->calc(base, &base->func->pstates[0].base); 154 ret = base->func->prog(&clk->base); 155 if (ret) { 156 nvkm_error(subdev, "cannot initialize clock\n"); 157 return ret; 158 } 159 160 return 0; 161 } 162 163 static const struct nvkm_clk_func 164 gm20b_clk_speedo0 = { 165 .init = gm20b_clk_init, 166 .fini = gk20a_clk_fini, 167 .read = gk20a_clk_read, 168 .calc = gk20a_clk_calc, 169 .prog = gk20a_clk_prog, 170 .tidy = gk20a_clk_tidy, 171 .pstates = gm20b_pstates, 172 .nr_pstates = ARRAY_SIZE(gm20b_pstates) - 1, 173 .domains = { 174 { nv_clk_src_crystal, 0xff }, 175 { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV }, 176 { nv_clk_src_max }, 177 }, 178 }; 179 180 int 181 gm20b_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) 182 { 183 struct gk20a_clk *clk; 184 int ret; 185 186 clk = kzalloc(sizeof(*clk), GFP_KERNEL); 187 if (!clk) 188 return -ENOMEM; 189 *pclk = &clk->base; 190 191 ret = _gk20a_clk_ctor(device, index, &gm20b_clk_speedo0, 192 &gm20b_pllg_params, clk); 193 194 clk->pl_to_div = pl_to_div; 195 clk->div_to_pl = div_to_pl; 196 197 return ret; 198 } 199