On 26/01/18 22:59, Lyude Paul wrote: > This enables BLCG optimization for kepler1. When using clockgating, > nvidia's firmware has a set of registers which are initially programmed > by the vbios with various engine delays and other mysterious settings > that are safe enough to bring up the GPU. However, the values used by > the vbios are more power hungry then they need to be, so the nvidia driver then -> than. With the comment about not exposing clock gating until patch 2, 3, and 4 have landed addressed, the series is: Reviewed-by: Martin Peres <martin.peres@xxxxxxx> Thanks a lot! I really like how this turned out :) > writes it's own more optimized set of BLCG settings before enabling > CG_CTRL. This adds support for programming the optimized BLCG values > during engine/subdev init, which enables rather significant power > savings. > > This introduces the nvkm_therm_clkgate_init() helper, which we use to > program the optimized BLCG settings before enabling clockgating with > nvkm_therm_clkgate_enable. > > As well, this commit shares a lot more code with Fermi since BLCG is > mostly the same there as far as we can tell. In the future, it's likely > we'll reformat the clkgate_packs for kepler1 so that they share a list > of mmio packs with Fermi. > > Signed-off-by: Lyude Paul <lyude@xxxxxxxxxx> > --- > .../gpu/drm/nouveau/include/nvkm/subdev/therm.h | 12 ++ > drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 1 + > drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 207 +++++++++++++++++++++ > drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h | 55 ++++++ > drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c | 6 + > drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c | 47 +++++ > drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h | 35 ++++ > drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | 2 + > drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild | 1 + > drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | 10 + > drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c | 75 ++++++++ > drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c | 1 + > drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c | 2 +- > drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h | 8 + > 14 files changed, 461 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h > create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h > create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c > > diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h > index 240b19bb4667..9398d9f09339 100644 > --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h > +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h > @@ -46,6 +46,16 @@ enum nvkm_therm_attr_type { > NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST = 17, > }; > > +struct nvkm_therm_clkgate_init { > + u32 addr; > + u8 count; > + u32 data; > +}; > + > +struct nvkm_therm_clkgate_pack { > + const struct nvkm_therm_clkgate_init *init; > +}; > + > struct nvkm_therm { > const struct nvkm_therm_func *func; > struct nvkm_subdev subdev; > @@ -92,6 +102,8 @@ struct nvkm_therm { > int nvkm_therm_temp_get(struct nvkm_therm *); > int nvkm_therm_fan_sense(struct nvkm_therm *); > int nvkm_therm_cstate(struct nvkm_therm *, int, int); > +void nvkm_therm_clkgate_init(struct nvkm_therm *, > + const struct nvkm_therm_clkgate_pack *); > void nvkm_therm_clkgate_enable(struct nvkm_therm *); > void nvkm_therm_clkgate_fini(struct nvkm_therm *, bool); > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h > index d7c2adb9b543..c8ec3fd97155 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h > @@ -137,6 +137,7 @@ struct gf100_gr_func { > int (*rops)(struct gf100_gr *); > int ppc_nr; > const struct gf100_grctx_func *grctx; > + const struct nvkm_therm_clkgate_pack *clkgate_pack; > struct nvkm_sclass sclass[]; > }; > > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c > index 5e82f94c2245..17cea9c70f7f 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c > @@ -22,6 +22,7 @@ > * Authors: Ben Skeggs <bskeggs@xxxxxxxxxx> > */ > #include "gf100.h" > +#include "gk104.h" > #include "ctxgf100.h" > > #include <nvif/class.h> > @@ -173,6 +174,208 @@ gk104_gr_pack_mmio[] = { > {} > }; > > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_main_0[] = { > + { 0x4041f0, 1, 0x00004046 }, > + { 0x409890, 1, 0x00000045 }, > + { 0x4098b0, 1, 0x0000007f }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_rstr2d_0[] = { > + { 0x4078c0, 1, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_unk_0[] = { > + { 0x406000, 1, 0x00004044 }, > + { 0x405860, 1, 0x00004042 }, > + { 0x40590c, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gcc_0[] = { > + { 0x408040, 1, 0x00004044 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_sked_0[] = { > + { 0x407000, 1, 0x00004044 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_unk_1[] = { > + { 0x405bf0, 1, 0x00004044 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_ctxctl_0[] = { > + { 0x41a890, 1, 0x00000042 }, > + { 0x41a8b0, 1, 0x0000007f }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_unk_0[] = { > + { 0x418500, 1, 0x00004042 }, > + { 0x418608, 1, 0x00004042 }, > + { 0x418688, 1, 0x00004042 }, > + { 0x418718, 1, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_esetup_0[] = { > + { 0x418828, 1, 0x00000044 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_tpbus_0[] = { > + { 0x418bbc, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_zcull_0[] = { > + { 0x418970, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_tpconf_0[] = { > + { 0x418c70, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_unk_1[] = { > + { 0x418cf0, 1, 0x00004042 }, > + { 0x418d70, 1, 0x00004042 }, > + { 0x418f0c, 1, 0x00004042 }, > + { 0x418e0c, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_gcc_0[] = { > + { 0x419020, 1, 0x00004042 }, > + { 0x419038, 1, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_ffb_0[] = { > + { 0x418898, 1, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_tex_0[] = { > + { 0x419a40, 9, 0x00004042 }, > + { 0x419acc, 1, 0x00004047 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_poly_0[] = { > + { 0x419868, 1, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_l1c_0[] = { > + { 0x419ccc, 3, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_unk_2[] = { > + { 0x419c70, 1, 0x00004045 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_mp_0[] = { > + { 0x419fd0, 1, 0x00004043 }, > + { 0x419fd8, 1, 0x00004049 }, > + { 0x419fe0, 2, 0x00004042 }, > + { 0x419ff0, 1, 0x00004046 }, > + { 0x419ff8, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_gpc_ppc_0[] = { > + { 0x41be28, 1, 0x00000042 }, > + { 0x41bfe8, 1, 0x00004042 }, > + { 0x41bed0, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_rop_zrop_0[] = { > + { 0x408810, 2, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_rop_0[] = { > + { 0x408a80, 6, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_rop_crop_0[] = { > + { 0x4089a8, 1, 0x00004042 }, > + { 0x4089b0, 1, 0x00000042 }, > + { 0x4089b8, 1, 0x00004042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_clkgate_blcg_init_pxbar_0[] = { > + { 0x13c820, 1, 0x0001007f }, > + { 0x13cbe0, 1, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_pack > +gk104_clkgate_pack[] = { > + { gk104_clkgate_blcg_init_main_0 }, > + { gk104_clkgate_blcg_init_rstr2d_0 }, > + { gk104_clkgate_blcg_init_unk_0 }, > + { gk104_clkgate_blcg_init_gcc_0 }, > + { gk104_clkgate_blcg_init_sked_0 }, > + { gk104_clkgate_blcg_init_unk_1 }, > + { gk104_clkgate_blcg_init_gpc_ctxctl_0 }, > + { gk104_clkgate_blcg_init_gpc_unk_0 }, > + { gk104_clkgate_blcg_init_gpc_esetup_0 }, > + { gk104_clkgate_blcg_init_gpc_tpbus_0 }, > + { gk104_clkgate_blcg_init_gpc_zcull_0 }, > + { gk104_clkgate_blcg_init_gpc_tpconf_0 }, > + { gk104_clkgate_blcg_init_gpc_unk_1 }, > + { gk104_clkgate_blcg_init_gpc_gcc_0 }, > + { gk104_clkgate_blcg_init_gpc_ffb_0 }, > + { gk104_clkgate_blcg_init_gpc_tex_0 }, > + { gk104_clkgate_blcg_init_gpc_poly_0 }, > + { gk104_clkgate_blcg_init_gpc_l1c_0 }, > + { gk104_clkgate_blcg_init_gpc_unk_2 }, > + { gk104_clkgate_blcg_init_gpc_mp_0 }, > + { gk104_clkgate_blcg_init_gpc_ppc_0 }, > + { gk104_clkgate_blcg_init_rop_zrop_0 }, > + { gk104_clkgate_blcg_init_rop_0 }, > + { gk104_clkgate_blcg_init_rop_crop_0 }, > + { gk104_clkgate_blcg_init_pxbar_0 }, > + {} > +}; > + > /******************************************************************************* > * PGRAPH engine/subdev functions > ******************************************************************************/ > @@ -214,6 +417,9 @@ gk104_gr_init(struct gf100_gr *gr) > gr->func->init_gpc_mmu(gr); > > gf100_gr_mmio(gr, gr->func->mmio); > + if (gr->func->clkgate_pack) > + nvkm_therm_clkgate_init(gr->base.engine.subdev.device->therm, > + gr->func->clkgate_pack); > > nvkm_wr32(device, GPC_UNIT(0, 0x3018), 0x00000001); > > @@ -338,6 +544,7 @@ gk104_gr = { > .rops = gf100_gr_rops, > .ppc_nr = 1, > .grctx = &gk104_grctx, > + .clkgate_pack = gk104_clkgate_pack, > .sclass = { > { -1, -1, FERMI_TWOD_A }, > { -1, -1, KEPLER_INLINE_TO_MEMORY_A }, > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h > new file mode 100644 > index 000000000000..a24c177365d1 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h > @@ -0,0 +1,55 @@ > +/* > + * Copyright 2018 Red Hat Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + * > + * Authors: Lyude Paul <lyude@xxxxxxxxxx> > + */ > +#ifndef __GK104_GR_H__ > +#define __GK104_GR_H__ > + > +#include <subdev/therm.h> > + > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_main_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rstr2d_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_unk_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gcc_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_sked_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_unk_1[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ctxctl_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_esetup_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tpbus_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_zcull_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tpconf_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_1[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_gcc_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ffb_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tex_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_poly_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_l1c_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_2[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_mp_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ppc_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_zrop_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_crop_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_pxbar_0[]; > + > +#endif > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c > index 47d28c279707..cdc4e0a2cc6b 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c > @@ -26,6 +26,7 @@ > > #include <core/memory.h> > #include <core/option.h> > +#include <subdev/therm.h> > > void > gf100_fb_intr(struct nvkm_fb *base) > @@ -92,6 +93,11 @@ gf100_fb_init(struct nvkm_fb *base) > > if (fb->r100c10_page) > nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8); > + > + if (base->func->clkgate_pack) { > + nvkm_therm_clkgate_init(device->therm, > + base->func->clkgate_pack); > + } > } > > void * > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c > index 0a6e8eaad42c..48fd98e08baa 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c > @@ -20,10 +20,56 @@ > * OTHER DEALINGS IN THE SOFTWARE. > * > * Authors: Ben Skeggs > + * Lyude Paul > */ > +#include "gk104.h" > #include "gf100.h" > #include "ram.h" > > +/* > + ******************************************************************************* > + * PGRAPH registers for clockgating > + ******************************************************************************* > + */ > +const struct nvkm_therm_clkgate_init > +gk104_fb_clkgate_blcg_init_unk_0[] = { > + { 0x100d10, 1, 0x0000c244 }, > + { 0x100d30, 1, 0x0000c242 }, > + { 0x100d3c, 1, 0x00000242 }, > + { 0x100d48, 1, 0x00000242 }, > + { 0x100d1c, 1, 0x00000042 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_fb_clkgate_blcg_init_vm_0[] = { > + { 0x100c98, 1, 0x00000242 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_fb_clkgate_blcg_init_main_0[] = { > + { 0x10f000, 1, 0x00000042 }, > + { 0x17e030, 1, 0x00000044 }, > + { 0x17e040, 1, 0x00000044 }, > + {} > +}; > + > +const struct nvkm_therm_clkgate_init > +gk104_fb_clkgate_blcg_init_bcast_0[] = { > + { 0x17ea60, 4, 0x00000044 }, > + {} > +}; > + > +static const struct nvkm_therm_clkgate_pack > +gk104_fb_clkgate_pack[] = { > + { gk104_fb_clkgate_blcg_init_unk_0 }, > + { gk104_fb_clkgate_blcg_init_vm_0 }, > + { gk104_fb_clkgate_blcg_init_main_0 }, > + { gk104_fb_clkgate_blcg_init_bcast_0 }, > + {} > +}; > + > static const struct nvkm_fb_func > gk104_fb = { > .dtor = gf100_fb_dtor, > @@ -33,6 +79,7 @@ gk104_fb = { > .intr = gf100_fb_intr, > .ram_new = gk104_ram_new, > .default_bigpage = 17, > + .clkgate_pack = gk104_fb_clkgate_pack, > }; > > int > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h > new file mode 100644 > index 000000000000..b3c78e4ff706 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h > @@ -0,0 +1,35 @@ > +/* > + * Copyright 2018 Red Hat Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + * > + * Authors: Lyude Paul > + */ > + > +#ifndef __GK104_FB_H__ > +#define __GK104_FB_H__ > + > +#include <subdev/therm.h> > + > +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_unk_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_vm_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_main_0[]; > +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_bcast_0[]; > + > +#endif > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h > index 9351188d5d76..414a423e0e55 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h > @@ -3,6 +3,7 @@ > #define __NVKM_FB_PRIV_H__ > #define nvkm_fb(p) container_of((p), struct nvkm_fb, subdev) > #include <subdev/fb.h> > +#include <subdev/therm.h> > struct nvkm_bios; > > struct nvkm_fb_func { > @@ -27,6 +28,7 @@ struct nvkm_fb_func { > int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); > > u8 default_bigpage; > + const struct nvkm_therm_clkgate_pack *clkgate_pack; > }; > > void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild > index 4bac4772d8ed..550702eab0b1 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild > @@ -9,6 +9,7 @@ nvkm-y += nvkm/subdev/therm/nv40.o > nvkm-y += nvkm/subdev/therm/nv50.o > nvkm-y += nvkm/subdev/therm/g84.o > nvkm-y += nvkm/subdev/therm/gt215.o > +nvkm-y += nvkm/subdev/therm/gf100.o > nvkm-y += nvkm/subdev/therm/gf119.o > nvkm-y += nvkm/subdev/therm/gk104.o > nvkm-y += nvkm/subdev/therm/gm107.o > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c > index e4c96e46db8f..bf62303571b3 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c > @@ -391,6 +391,16 @@ nvkm_therm_init(struct nvkm_subdev *subdev) > return 0; > } > > +void > +nvkm_therm_clkgate_init(struct nvkm_therm *therm, > + const struct nvkm_therm_clkgate_pack *p) > +{ > + if (!therm->func->clkgate_init || !therm->clkgating_enabled) > + return; > + > + therm->func->clkgate_init(therm, p); > +} > + > static void * > nvkm_therm_dtor(struct nvkm_subdev *subdev) > { > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c > new file mode 100644 > index 000000000000..a0da7f8b7d93 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c > @@ -0,0 +1,75 @@ > +/* > + * Copyright 2018 Red Hat Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR > + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR > + * OTHER DEALINGS IN THE SOFTWARE. > + * > + * Authors: Lyude Paul > + */ > +#include <core/device.h> > + > +#include "priv.h" > + > +#define pack_for_each_init(init, pack, head) \ > + for (pack = head; pack && pack->init; pack++) \ > + for (init = pack->init; init && init->count; init++) > +void > +gf100_clkgate_init(struct nvkm_therm *therm, > + const struct nvkm_therm_clkgate_pack *p) > +{ > + struct nvkm_device *device = therm->subdev.device; > + const struct nvkm_therm_clkgate_pack *pack; > + const struct nvkm_therm_clkgate_init *init; > + u32 next, addr; > + > + pack_for_each_init(init, pack, p) { > + next = init->addr + init->count * 8; > + addr = init->addr; > + > + nvkm_trace(&therm->subdev, "{ 0x%06x, %d, 0x%08x }\n", > + init->addr, init->count, init->data); > + while (addr < next) { > + nvkm_trace(&therm->subdev, "\t0x%06x = 0x%08x\n", > + addr, init->data); > + nvkm_wr32(device, addr, init->data); > + addr += 8; > + } > + } > +} > + > +static const struct nvkm_therm_func > +gf100_therm_func = { > + .init = gt215_therm_init, > + .fini = g84_therm_fini, > + .pwm_ctrl = nv50_fan_pwm_ctrl, > + .pwm_get = nv50_fan_pwm_get, > + .pwm_set = nv50_fan_pwm_set, > + .pwm_clock = nv50_fan_pwm_clock, > + .temp_get = g84_temp_get, > + .fan_sense = gt215_therm_fan_sense, > + .program_alarms = nvkm_therm_program_alarms_polling, > + /* TODO: Fermi clockgating isn't understood fully yet, so we leave it > + * disabled here */ > +}; > + > +int > +gf100_therm_new(struct nvkm_device *device, int index, > + struct nvkm_therm **ptherm) > +{ > + return nvkm_therm_new_(&gf100_therm_func, device, index, ptherm); > +} > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c > index 79806a757893..4e03971d2e3d 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c > @@ -100,6 +100,7 @@ gk104_therm_func = { > .temp_get = g84_temp_get, > .fan_sense = gt215_therm_fan_sense, > .program_alarms = nvkm_therm_program_alarms_polling, > + .clkgate_init = gf100_clkgate_init, > .clkgate_enable = gk104_clkgate_enable, > .clkgate_fini = gk104_clkgate_fini, > }; > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c > index c08097f2aff5..4caf401d001a 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c > @@ -36,7 +36,7 @@ gt215_therm_fan_sense(struct nvkm_therm *therm) > return -ENODEV; > } > > -static void > +void > gt215_therm_init(struct nvkm_therm *therm) > { > struct nvkm_device *device = therm->subdev.device; > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h > index f30202dd88e7..a737e9b8a584 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h > @@ -97,6 +97,8 @@ struct nvkm_therm_func { > > void (*program_alarms)(struct nvkm_therm *); > > + void (*clkgate_init)(struct nvkm_therm *, > + const struct nvkm_therm_clkgate_pack *); > void (*clkgate_enable)(struct nvkm_therm *); > void (*clkgate_fini)(struct nvkm_therm *, bool); > }; > @@ -114,6 +116,9 @@ void g84_therm_fini(struct nvkm_therm *); > > int gt215_therm_fan_sense(struct nvkm_therm *); > > +void gf100_clkgate_init(struct nvkm_therm *, > + const struct nvkm_therm_clkgate_pack *); > + > void g84_therm_init(struct nvkm_therm *); > > int gf119_fan_pwm_ctrl(struct nvkm_therm *, int, bool); > @@ -122,6 +127,9 @@ int gf119_fan_pwm_set(struct nvkm_therm *, int, u32, u32); > int gf119_fan_pwm_clock(struct nvkm_therm *, int); > void gf119_therm_init(struct nvkm_therm *); > > +void gt215_therm_init(struct nvkm_therm *therm); > + > +void gk104_therm_init(struct nvkm_therm *); > void gk104_clkgate_enable(struct nvkm_therm *); > void gk104_clkgate_fini(struct nvkm_therm *, bool); > > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel