drm/nouveau: Support reclocking on gp10b
Starting with Tegra186, gpu clock handling is done by the bpmp and there is little to be done by the kernel. The only thing necessary for reclocking is to set the gpcclk to the desired rate and the bpmp handles the rest. The pstate list is based on the downstream driver generates. Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
This commit is contained in:
@@ -134,4 +134,5 @@ int gf100_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
|
|||||||
int gk104_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
int gk104_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||||
int gk20a_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
int gk20a_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||||
int gm20b_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
int gm20b_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||||
|
int gp10b_clk_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_clk **);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2280,6 +2280,7 @@ nv13b_chipset = {
|
|||||||
.acr = { 0x00000001, gp10b_acr_new },
|
.acr = { 0x00000001, gp10b_acr_new },
|
||||||
.bar = { 0x00000001, gm20b_bar_new },
|
.bar = { 0x00000001, gm20b_bar_new },
|
||||||
.bus = { 0x00000001, gf100_bus_new },
|
.bus = { 0x00000001, gf100_bus_new },
|
||||||
|
.clk = { 0x00000001, gp10b_clk_new },
|
||||||
.fault = { 0x00000001, gp10b_fault_new },
|
.fault = { 0x00000001, gp10b_fault_new },
|
||||||
.fb = { 0x00000001, gp10b_fb_new },
|
.fb = { 0x00000001, gp10b_fb_new },
|
||||||
.fuse = { 0x00000001, gm107_fuse_new },
|
.fuse = { 0x00000001, gm107_fuse_new },
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ nvkm-y += nvkm/subdev/clk/gf100.o
|
|||||||
nvkm-y += nvkm/subdev/clk/gk104.o
|
nvkm-y += nvkm/subdev/clk/gk104.o
|
||||||
nvkm-y += nvkm/subdev/clk/gk20a.o
|
nvkm-y += nvkm/subdev/clk/gk20a.o
|
||||||
nvkm-y += nvkm/subdev/clk/gm20b.o
|
nvkm-y += nvkm/subdev/clk/gm20b.o
|
||||||
|
nvkm-y += nvkm/subdev/clk/gp10b.o
|
||||||
|
|
||||||
nvkm-y += nvkm/subdev/clk/pllnv04.o
|
nvkm-y += nvkm/subdev/clk/pllnv04.o
|
||||||
nvkm-y += nvkm/subdev/clk/pllgt215.o
|
nvkm-y += nvkm/subdev/clk/pllgt215.o
|
||||||
|
|||||||
180
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gp10b.c
Normal file
180
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gp10b.c
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
#include <subdev/clk.h>
|
||||||
|
#include <subdev/timer.h>
|
||||||
|
#include <core/device.h>
|
||||||
|
#include <core/tegra.h>
|
||||||
|
|
||||||
|
#include "priv.h"
|
||||||
|
#include "gk20a.h"
|
||||||
|
#include "gp10b.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
gp10b_clk_init(struct nvkm_clk *base)
|
||||||
|
{
|
||||||
|
struct gp10b_clk *clk = gp10b_clk(base);
|
||||||
|
struct nvkm_subdev *subdev = &clk->base.subdev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Start with the highest frequency, matching the BPMP default */
|
||||||
|
base->func->calc(base, &base->func->pstates[base->func->nr_pstates - 1].base);
|
||||||
|
ret = base->func->prog(base);
|
||||||
|
if (ret) {
|
||||||
|
nvkm_error(subdev, "cannot initialize clock\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
gp10b_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
|
||||||
|
{
|
||||||
|
struct gp10b_clk *clk = gp10b_clk(base);
|
||||||
|
struct nvkm_subdev *subdev = &clk->base.subdev;
|
||||||
|
|
||||||
|
switch (src) {
|
||||||
|
case nv_clk_src_gpc:
|
||||||
|
return clk_get_rate(clk->clk) / GK20A_CLK_GPC_MDIV;
|
||||||
|
default:
|
||||||
|
nvkm_error(subdev, "invalid clock source %d\n", src);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gp10b_clk_calc(struct nvkm_clk *base, struct nvkm_cstate *cstate)
|
||||||
|
{
|
||||||
|
struct gp10b_clk *clk = gp10b_clk(base);
|
||||||
|
u32 target_rate = cstate->domain[nv_clk_src_gpc] * GK20A_CLK_GPC_MDIV;
|
||||||
|
|
||||||
|
clk->new_rate = clk_round_rate(clk->clk, target_rate) / GK20A_CLK_GPC_MDIV;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gp10b_clk_prog(struct nvkm_clk *base)
|
||||||
|
{
|
||||||
|
struct gp10b_clk *clk = gp10b_clk(base);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_set_rate(clk->clk, clk->new_rate * GK20A_CLK_GPC_MDIV);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
clk->rate = clk_get_rate(clk->clk) / GK20A_CLK_GPC_MDIV;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nvkm_pstate
|
||||||
|
gp10b_pstates[] = {
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 114750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 216750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 318750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 420750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 522750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 624750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 726750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 828750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 930750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 1032750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 1134750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 1236750,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.base = {
|
||||||
|
.domain[nv_clk_src_gpc] = 1300500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct nvkm_clk_func
|
||||||
|
gp10b_clk = {
|
||||||
|
.init = gp10b_clk_init,
|
||||||
|
.read = gp10b_clk_read,
|
||||||
|
.calc = gp10b_clk_calc,
|
||||||
|
.prog = gp10b_clk_prog,
|
||||||
|
.tidy = gk20a_clk_tidy,
|
||||||
|
.pstates = gp10b_pstates,
|
||||||
|
.nr_pstates = ARRAY_SIZE(gp10b_pstates),
|
||||||
|
.domains = {
|
||||||
|
{ nv_clk_src_gpc, 0xff, 0, "core", GK20A_CLK_GPC_MDIV },
|
||||||
|
{ nv_clk_src_max }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
gp10b_clk_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
|
||||||
|
struct nvkm_clk **pclk)
|
||||||
|
{
|
||||||
|
struct nvkm_device_tegra *tdev = device->func->tegra(device);
|
||||||
|
const struct nvkm_clk_func *func = &gp10b_clk;
|
||||||
|
struct gp10b_clk *clk;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
|
||||||
|
if (!clk)
|
||||||
|
return -ENOMEM;
|
||||||
|
*pclk = &clk->base;
|
||||||
|
clk->clk = tdev->clk;
|
||||||
|
|
||||||
|
/* Finish initializing the pstates */
|
||||||
|
for (i = 0; i < func->nr_pstates; i++) {
|
||||||
|
INIT_LIST_HEAD(&func->pstates[i].list);
|
||||||
|
func->pstates[i].pstate = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nvkm_clk_ctor(func, device, type, inst, true, &clk->base);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
16
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gp10b.h
Normal file
16
drivers/gpu/drm/nouveau/nvkm/subdev/clk/gp10b.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
#ifndef __NVKM_CLK_GP10B_H__
|
||||||
|
#define __NVKM_CLK_GP10B_H__
|
||||||
|
|
||||||
|
struct gp10b_clk {
|
||||||
|
/* currently applied parameters */
|
||||||
|
struct nvkm_clk base;
|
||||||
|
struct clk *clk;
|
||||||
|
u32 rate;
|
||||||
|
|
||||||
|
/* new parameters to apply */
|
||||||
|
u32 new_rate;
|
||||||
|
};
|
||||||
|
#define gp10b_clk(p) container_of((p), struct gp10b_clk, base)
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user