linux/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gm20b.c
<<
>>
Prefs
   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
  38static u32 pl_to_div(u32 pl)
  39{
  40        return pl;
  41}
  42
  43static u32 div_to_pl(u32 div)
  44{
  45        return div;
  46}
  47
  48static 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
  56static struct nvkm_pstate
  57gm20b_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
 139static int
 140gm20b_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
 163static const struct nvkm_clk_func
 164gm20b_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
 180int
 181gm20b_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