1d5603737SAaron Kling // SPDX-License-Identifier: MIT 2d5603737SAaron Kling #include <subdev/clk.h> 3d5603737SAaron Kling #include <subdev/timer.h> 4d5603737SAaron Kling #include <core/device.h> 5d5603737SAaron Kling #include <core/tegra.h> 6d5603737SAaron Kling 7d5603737SAaron Kling #include "priv.h" 8*6ca1701cSAaron Kling #include "gk20a_devfreq.h" 9d5603737SAaron Kling #include "gk20a.h" 10d5603737SAaron Kling #include "gp10b.h" 11d5603737SAaron Kling 12d5603737SAaron Kling static int 13d5603737SAaron Kling gp10b_clk_init(struct nvkm_clk *base) 14d5603737SAaron Kling { 15d5603737SAaron Kling struct gp10b_clk *clk = gp10b_clk(base); 16d5603737SAaron Kling struct nvkm_subdev *subdev = &clk->base.subdev; 17d5603737SAaron Kling int ret; 18d5603737SAaron Kling 19d5603737SAaron Kling /* Start with the highest frequency, matching the BPMP default */ 20d5603737SAaron Kling base->func->calc(base, &base->func->pstates[base->func->nr_pstates - 1].base); 21d5603737SAaron Kling ret = base->func->prog(base); 22d5603737SAaron Kling if (ret) { 23d5603737SAaron Kling nvkm_error(subdev, "cannot initialize clock\n"); 24d5603737SAaron Kling return ret; 25d5603737SAaron Kling } 26d5603737SAaron Kling 27*6ca1701cSAaron Kling ret = gk20a_devfreq_init(base, &clk->devfreq); 28*6ca1701cSAaron Kling if (ret) 29*6ca1701cSAaron Kling return ret; 30*6ca1701cSAaron Kling 31d5603737SAaron Kling return 0; 32d5603737SAaron Kling } 33d5603737SAaron Kling 34d5603737SAaron Kling static int 35d5603737SAaron Kling gp10b_clk_read(struct nvkm_clk *base, enum nv_clk_src src) 36d5603737SAaron Kling { 37d5603737SAaron Kling struct gp10b_clk *clk = gp10b_clk(base); 38d5603737SAaron Kling struct nvkm_subdev *subdev = &clk->base.subdev; 39d5603737SAaron Kling 40d5603737SAaron Kling switch (src) { 41d5603737SAaron Kling case nv_clk_src_gpc: 42d5603737SAaron Kling return clk_get_rate(clk->clk) / GK20A_CLK_GPC_MDIV; 43d5603737SAaron Kling default: 44d5603737SAaron Kling nvkm_error(subdev, "invalid clock source %d\n", src); 45d5603737SAaron Kling return -EINVAL; 46d5603737SAaron Kling } 47d5603737SAaron Kling } 48d5603737SAaron Kling 49d5603737SAaron Kling static int 50d5603737SAaron Kling gp10b_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate) 51d5603737SAaron Kling { 52d5603737SAaron Kling struct gp10b_clk *clk = gp10b_clk(base); 53d5603737SAaron Kling u32 target_rate = cstate->domain[nv_clk_src_gpc] * GK20A_CLK_GPC_MDIV; 54d5603737SAaron Kling 55d5603737SAaron Kling clk->new_rate = clk_round_rate(clk->clk, target_rate) / GK20A_CLK_GPC_MDIV; 56d5603737SAaron Kling 57d5603737SAaron Kling return 0; 58d5603737SAaron Kling } 59d5603737SAaron Kling 60d5603737SAaron Kling static int 61d5603737SAaron Kling gp10b_clk_prog(struct nvkm_clk *base) 62d5603737SAaron Kling { 63d5603737SAaron Kling struct gp10b_clk *clk = gp10b_clk(base); 64d5603737SAaron Kling int ret; 65d5603737SAaron Kling 66d5603737SAaron Kling ret = clk_set_rate(clk->clk, clk->new_rate * GK20A_CLK_GPC_MDIV); 67d5603737SAaron Kling if (ret < 0) 68d5603737SAaron Kling return ret; 69d5603737SAaron Kling 70d5603737SAaron Kling clk->rate = clk_get_rate(clk->clk) / GK20A_CLK_GPC_MDIV; 71d5603737SAaron Kling 72d5603737SAaron Kling return 0; 73d5603737SAaron Kling } 74d5603737SAaron Kling 75d5603737SAaron Kling static struct nvkm_pstate 76d5603737SAaron Kling gp10b_pstates[] = { 77d5603737SAaron Kling { 78d5603737SAaron Kling .base = { 79d5603737SAaron Kling .domain[nv_clk_src_gpc] = 114750, 80d5603737SAaron Kling }, 81d5603737SAaron Kling }, 82d5603737SAaron Kling { 83d5603737SAaron Kling .base = { 84d5603737SAaron Kling .domain[nv_clk_src_gpc] = 216750, 85d5603737SAaron Kling }, 86d5603737SAaron Kling }, 87d5603737SAaron Kling { 88d5603737SAaron Kling .base = { 89d5603737SAaron Kling .domain[nv_clk_src_gpc] = 318750, 90d5603737SAaron Kling }, 91d5603737SAaron Kling }, 92d5603737SAaron Kling { 93d5603737SAaron Kling .base = { 94d5603737SAaron Kling .domain[nv_clk_src_gpc] = 420750, 95d5603737SAaron Kling }, 96d5603737SAaron Kling }, 97d5603737SAaron Kling { 98d5603737SAaron Kling .base = { 99d5603737SAaron Kling .domain[nv_clk_src_gpc] = 522750, 100d5603737SAaron Kling }, 101d5603737SAaron Kling }, 102d5603737SAaron Kling { 103d5603737SAaron Kling .base = { 104d5603737SAaron Kling .domain[nv_clk_src_gpc] = 624750, 105d5603737SAaron Kling }, 106d5603737SAaron Kling }, 107d5603737SAaron Kling { 108d5603737SAaron Kling .base = { 109d5603737SAaron Kling .domain[nv_clk_src_gpc] = 726750, 110d5603737SAaron Kling }, 111d5603737SAaron Kling }, 112d5603737SAaron Kling { 113d5603737SAaron Kling .base = { 114d5603737SAaron Kling .domain[nv_clk_src_gpc] = 828750, 115d5603737SAaron Kling }, 116d5603737SAaron Kling }, 117d5603737SAaron Kling { 118d5603737SAaron Kling .base = { 119d5603737SAaron Kling .domain[nv_clk_src_gpc] = 930750, 120d5603737SAaron Kling }, 121d5603737SAaron Kling }, 122d5603737SAaron Kling { 123d5603737SAaron Kling .base = { 124d5603737SAaron Kling .domain[nv_clk_src_gpc] = 1032750, 125d5603737SAaron Kling }, 126d5603737SAaron Kling }, 127d5603737SAaron Kling { 128d5603737SAaron Kling .base = { 129d5603737SAaron Kling .domain[nv_clk_src_gpc] = 1134750, 130d5603737SAaron Kling }, 131d5603737SAaron Kling }, 132d5603737SAaron Kling { 133d5603737SAaron Kling .base = { 134d5603737SAaron Kling .domain[nv_clk_src_gpc] = 1236750, 135d5603737SAaron Kling }, 136d5603737SAaron Kling }, 137d5603737SAaron Kling { 138d5603737SAaron Kling .base = { 139d5603737SAaron Kling .domain[nv_clk_src_gpc] = 1300500, 140d5603737SAaron Kling }, 141d5603737SAaron Kling }, 142d5603737SAaron Kling }; 143d5603737SAaron Kling 144d5603737SAaron Kling static const struct nvkm_clk_func 145d5603737SAaron Kling gp10b_clk = { 146d5603737SAaron Kling .init = gp10b_clk_init, 147d5603737SAaron Kling .read = gp10b_clk_read, 148d5603737SAaron Kling .calc = gp10b_clk_calc, 149d5603737SAaron Kling .prog = gp10b_clk_prog, 150d5603737SAaron Kling .tidy = gk20a_clk_tidy, 151d5603737SAaron Kling .pstates = gp10b_pstates, 152d5603737SAaron Kling .nr_pstates = ARRAY_SIZE(gp10b_pstates), 153d5603737SAaron Kling .domains = { 154d5603737SAaron Kling { nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV }, 155d5603737SAaron Kling { nv_clk_src_max } 156d5603737SAaron Kling } 157d5603737SAaron Kling }; 158d5603737SAaron Kling 159d5603737SAaron Kling int 160d5603737SAaron Kling gp10b_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, 161d5603737SAaron Kling struct nvkm_clk **pclk) 162d5603737SAaron Kling { 163d5603737SAaron Kling struct nvkm_device_tegra *tdev = device->func->tegra(device); 164d5603737SAaron Kling const struct nvkm_clk_func *func = &gp10b_clk; 165d5603737SAaron Kling struct gp10b_clk *clk; 166d5603737SAaron Kling int ret, i; 167d5603737SAaron Kling 168d5603737SAaron Kling clk = kzalloc(sizeof(*clk), GFP_KERNEL); 169d5603737SAaron Kling if (!clk) 170d5603737SAaron Kling return -ENOMEM; 171d5603737SAaron Kling *pclk = &clk->base; 172d5603737SAaron Kling clk->clk = tdev->clk; 173d5603737SAaron Kling 174d5603737SAaron Kling /* Finish initializing the pstates */ 175d5603737SAaron Kling for (i = 0; i < func->nr_pstates; i++) { 176d5603737SAaron Kling INIT_LIST_HEAD(&func->pstates[i].list); 177d5603737SAaron Kling func->pstates[i].pstate = i + 1; 178d5603737SAaron Kling } 179d5603737SAaron Kling 180d5603737SAaron Kling ret = nvkm_clk_ctor(func, device, type, inst, true, &clk->base); 181d5603737SAaron Kling if (ret) 182d5603737SAaron Kling return ret; 183d5603737SAaron Kling 184d5603737SAaron Kling return 0; 185d5603737SAaron Kling } 186