From b17d9708c9e9930778de43de1edf1385acb13ebd Mon Sep 17 00:00:00 2001 From: Vijayakumar Subbu Date: Wed, 27 Jul 2016 22:29:15 -0700 Subject: gpu: nvgpu: Add dGPU clocks support JIRA DNVGPU-45 Change-Id: I237ce81e31b036c05c82d46eea8694ffe1c2e3df Signed-off-by: Mahantesh Kumbar Signed-off-by: Vijayakumar Subbu Reviewed-on: http://git-master/r/1205849 (cherry picked from commit 9a4006f76b75a8ad525e7aa5ad1f609aaae49126) Reviewed-on: http://git-master/r/1227256 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile.nvgpu | 7 +- drivers/gpu/nvgpu/boardobj/boardobj.c | 80 +++ drivers/gpu/nvgpu/boardobj/boardobj.h | 83 +++ drivers/gpu/nvgpu/boardobj/boardobjgrp.c | 697 ++++++++++++++++++++++++++ drivers/gpu/nvgpu/boardobj/boardobjgrp.h | 390 ++++++++++++++ drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.c | 92 ++++ drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.h | 45 ++ drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.c | 91 ++++ drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.h | 59 +++ drivers/gpu/nvgpu/boardobj/boardobjgrpmask.c | 357 +++++++++++++ drivers/gpu/nvgpu/boardobj/boardobjgrpmask.h | 110 ++++ drivers/gpu/nvgpu/ctrl/ctrlboardobj.h | 81 +++ drivers/gpu/nvgpu/ctrl/ctrlclk.h | 153 ++++++ drivers/gpu/nvgpu/ctrl/ctrlclkavfs.h | 88 ++++ drivers/gpu/nvgpu/ctrl/ctrlperf.h | 32 ++ drivers/gpu/nvgpu/ctrl/ctrlvolt.h | 40 ++ drivers/gpu/nvgpu/gk20a/gk20a.c | 23 + drivers/gpu/nvgpu/gk20a/gk20a.h | 12 + drivers/gpu/nvgpu/gk20a/hal_gk20a.c | 1 + drivers/gpu/nvgpu/gk20a/pmu_api.h | 23 + drivers/gpu/nvgpu/gk20a/pmu_common.h | 38 +- drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 3 - drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 38 +- drivers/gpu/nvgpu/gm206/bios_gm206.c | 25 +- drivers/gpu/nvgpu/gm206/bios_gm206.h | 20 +- drivers/gpu/nvgpu/gm206/hal_gm206.c | 2 +- drivers/gpu/nvgpu/gm20b/hal_gm20b.c | 1 + drivers/gpu/nvgpu/pmuif/gpmuifbios.h | 41 ++ drivers/gpu/nvgpu/pmuif/gpmuifboardobj.h | 196 ++++++++ drivers/gpu/nvgpu/pmuif/gpmuifclk.h | 414 +++++++++++++++ drivers/gpu/nvgpu/pmuif/gpmuifperf.h | 116 +++++ drivers/gpu/nvgpu/pmuif/gpmuifperfvfe.h | 220 ++++++++ drivers/gpu/nvgpu/pmuif/gpmuifvolt.h | 33 ++ 33 files changed, 3575 insertions(+), 36 deletions(-) create mode 100644 drivers/gpu/nvgpu/boardobj/boardobj.c create mode 100644 drivers/gpu/nvgpu/boardobj/boardobj.h create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrp.c create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrp.h create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.c create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.h create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.c create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.h create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrpmask.c create mode 100644 drivers/gpu/nvgpu/boardobj/boardobjgrpmask.h create mode 100644 drivers/gpu/nvgpu/ctrl/ctrlboardobj.h create mode 100644 drivers/gpu/nvgpu/ctrl/ctrlclk.h create mode 100644 drivers/gpu/nvgpu/ctrl/ctrlclkavfs.h create mode 100644 drivers/gpu/nvgpu/ctrl/ctrlperf.h create mode 100644 drivers/gpu/nvgpu/ctrl/ctrlvolt.h create mode 100644 drivers/gpu/nvgpu/pmuif/gpmuifbios.h create mode 100644 drivers/gpu/nvgpu/pmuif/gpmuifboardobj.h create mode 100644 drivers/gpu/nvgpu/pmuif/gpmuifclk.h create mode 100644 drivers/gpu/nvgpu/pmuif/gpmuifperf.h create mode 100644 drivers/gpu/nvgpu/pmuif/gpmuifperfvfe.h create mode 100644 drivers/gpu/nvgpu/pmuif/gpmuifvolt.h (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index 33d158bb..22c679ca 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu +++ b/drivers/gpu/nvgpu/Makefile.nvgpu @@ -88,7 +88,12 @@ nvgpu-y := \ gm206/acr_gm206.o \ gm206/mm_gm206.o \ gm206/pmu_gm206.o \ - gm206/ce_gm206.o + gm206/ce_gm206.o \ + boardobj/boardobj.o \ + boardobj/boardobjgrp.o \ + boardobj/boardobjgrpmask.o \ + boardobj/boardobjgrp_e255.o \ + boardobj/boardobjgrp_e32.o nvgpu-$(CONFIG_TEGRA_GK20A) += gk20a/platform_gk20a_tegra.o nvgpu-$(CONFIG_SYNC) += gk20a/sync_gk20a.o diff --git a/drivers/gpu/nvgpu/boardobj/boardobj.c b/drivers/gpu/nvgpu/boardobj/boardobj.c new file mode 100644 index 00000000..86b639cc --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobj.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "gk20a/gk20a.h" +#include +#include +#include +#include "boardobj.h" +#include "ctrl/ctrlboardobj.h" +#include "pmuif/gpmuifboardobj.h" + + +u32 boardobj_construct_super(struct gk20a *g, struct boardobj **ppboardobj, + u16 size, void *args) +{ + struct boardobj *pboardobj = NULL; + struct boardobj *devtmp = (struct boardobj *)args; + + gk20a_dbg_info(" "); + + if (devtmp == NULL) + return -EINVAL; + + if (*ppboardobj == NULL) { + *ppboardobj = kzalloc(size, GFP_KERNEL); + if (ppboardobj == NULL) + return -ENOMEM; + } + + pboardobj = *ppboardobj; + pboardobj->type = devtmp->type; + pboardobj->idx = CTRL_BOARDOBJ_IDX_INVALID; + pboardobj->type_mask = BIT(pboardobj->type) | devtmp->type_mask; + + pboardobj->implements = boardobj_implements_super; + pboardobj->destruct = boardobj_destruct_super; + pboardobj->pmudatainit = boardobj_pmudatainit_super; + + return 0; +} + +u32 boardobj_destruct_super(struct boardobj *pboardobj) +{ + gk20a_dbg_info(""); + if (pboardobj == NULL) + return -EINVAL; + kfree(pboardobj); + return 0; +} + +bool boardobj_implements_super(struct gk20a *g, struct boardobj *pboardobj, + u8 type) +{ + gk20a_dbg_info(""); + + return (0 != (pboardobj->type_mask & BIT(type))); +} + +u32 boardobj_pmudatainit_super(struct gk20a *g, struct boardobj *pboardobj, + struct nv_pmu_boardobj *pmudata) +{ + gk20a_dbg_info(""); + if (pboardobj == NULL) + return -EINVAL; + if (pmudata == NULL) + return -EINVAL; + pmudata->type = pboardobj->type; + gk20a_dbg_info(" Done"); + return 0; +} diff --git a/drivers/gpu/nvgpu/boardobj/boardobj.h b/drivers/gpu/nvgpu/boardobj/boardobj.h new file mode 100644 index 00000000..3d437a82 --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobj.h @@ -0,0 +1,83 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ + +#ifndef _BOARDOBJ_H_ +#define _BOARDOBJ_H_ + +struct boardobj; + +#include +#include "gk20a/gk20a.h" +#include "gk20a/pmu_gk20a.h" +#include "ctrl/ctrlboardobj.h" +#include "pmuif/gpmuifboardobj.h" + +/* +* check whether the specified BOARDOBJ object implements the queried +* type/class enumeration. +*/ +typedef bool boardobj_implements(struct gk20a *g, struct boardobj *pboardobj, + u8 type); + +/* +* Fills out the appropriate the nv_pmu_xxxx_device_desc_ driver->PMU +* description structure, describing this BOARDOBJ board device to the PMU. +* +*/ +typedef u32 boardobj_pmudatainit(struct gk20a *g, struct boardobj *pboardobj, + struct nv_pmu_boardobj *pmudata); + +/* +* Constructor for the base Board Object. Called by each device-specific +* implementation of the BOARDOBJ interface to initialize the board object. +*/ +typedef u32 boardobj_construct(struct gk20a *g, struct boardobj **pboardobj, + u16 size, void *args); + +/* +* Destructor for the base board object. Called by each device-Specific +* implementation of the BOARDOBJ interface to destroy the board object. +* This has to be explicitly set by each device that extends from the +* board object. +*/ +typedef u32 boardobj_destruct(struct boardobj *pboardobj); + +/* +* Base Class for all physical or logical device on the PCB. +* Contains fields common to all devices on the board. Specific types of +* devices may extend this object adding any details specific to that +* device or device-type. +*/ + +struct boardobj { + u8 type; /*type of the device*/ + u8 idx; /*index of boardobj within in its group*/ + u32 type_mask; /*mask of types this boardobjimplements*/ + boardobj_implements *implements; + boardobj_destruct *destruct; + /* + * Access interface apis which will be overridden by the devices + * that inherit from BOARDOBJ + */ + boardobj_pmudatainit *pmudatainit; +}; + +boardobj_construct boardobj_construct_super; +boardobj_destruct boardobj_destruct_super; +boardobj_implements boardobj_implements_super; +boardobj_pmudatainit boardobj_pmudatainit_super; + +#define BOARDOBJ_GET_TYPE(pobj) (((struct boardobj *)(pobj))->type) +#define BOARDOBJ_GET_IDX(pobj) (((struct boardobj *)(pobj))->idx) + +#endif diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp.c b/drivers/gpu/nvgpu/boardobj/boardobjgrp.c new file mode 100644 index 00000000..dfa394ed --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp.c @@ -0,0 +1,697 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ + +#include "gk20a/gk20a.h" +#include "gk20a/pmu_gk20a.h" +#include "boardobjgrp.h" +#include "ctrl/ctrlboardobj.h" +#include "boardobj.h" + +static boardobjgrp_objinsert boardobjgrp_objinsert_final; +static boardobjgrp_objgetbyidx boardobjgrp_objgetbyidx_final; +static boardobjgrp_objgetnext boardobjgrp_objgetnext_final; +static boardobjgrp_objremoveanddestroy boardobjgrp_objremoveanddestroy_final; +static boardobjgrp_pmudatainstget boardobjgrp_pmudatainstget_stub; +static boardobjgrp_pmustatusinstget boardobjgrp_pmustatusinstget_stub; +static u32 boardobjgrp_pmucmdsend(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct boardobjgrp_pmu_cmd *pcmd); +struct boardobjgrp_pmucmdhandler_params { + /* Pointer to the BOARDOBJGRP associated with this CMD */ + struct boardobjgrp *pboardobjgrp; + /* Pointer to structure representing this NV_PMU_BOARDOBJ_CMD_GRP */ + struct boardobjgrp_pmu_cmd *pcmd; + /* Boolean indicating whether the PMU successfully handled the CMD */ + u32 success; +}; + +u32 boardobjgrp_construct_super(struct boardobjgrp *pboardobjgrp) +{ + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + + if (pboardobjgrp->ppobjects == NULL) + return -EINVAL; + + if (pboardobjgrp->mask == NULL) + return -EINVAL; + + pboardobjgrp->objmask = 0; + + pboardobjgrp->classid = 0; + pboardobjgrp->pmu.unitid = BOARDOBJGRP_UNIT_ID_INVALID; + pboardobjgrp->pmu.classid = BOARDOBJGRP_GRP_CLASS_ID_INVALID; + pboardobjgrp->pmu.set.id = BOARDOBJGRP_GRP_CMD_ID_INVALID; + pboardobjgrp->pmu.getstatus.id = BOARDOBJGRP_GRP_CMD_ID_INVALID; + + /* Initialize basic interfaces */ + pboardobjgrp->destruct = boardobjgrp_destruct_super; + pboardobjgrp->objinsert = boardobjgrp_objinsert_final; + pboardobjgrp->objgetbyidx = boardobjgrp_objgetbyidx_final; + pboardobjgrp->objgetnext = boardobjgrp_objgetnext_final; + pboardobjgrp->objremoveanddestroy = + boardobjgrp_objremoveanddestroy_final; + + pboardobjgrp->pmuinithandle = boardobjgrp_pmuinithandle_impl; + pboardobjgrp->pmuhdrdatainit = boardobjgrp_pmuhdrdatainit_super; + pboardobjgrp->pmudatainit = boardobjgrp_pmudatainit_super; + pboardobjgrp->pmuset = boardobjgrp_pmuset_impl; + pboardobjgrp->pmugetstatus = boardobjgrp_pmugetstatus_impl; + + pboardobjgrp->pmudatainstget = boardobjgrp_pmudatainstget_stub; + pboardobjgrp->pmustatusinstget = boardobjgrp_pmustatusinstget_stub; + + pboardobjgrp->objmaxidx = CTRL_BOARDOBJ_IDX_INVALID; + pboardobjgrp->bconstructed = true; + + return 0; +} + +u32 boardobjgrp_destruct_impl(struct boardobjgrp *pboardobjgrp) +{ + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + + if (!pboardobjgrp->bconstructed) + return 0; + + return pboardobjgrp->destruct(pboardobjgrp); +} + +u32 boardobjgrp_destruct_super(struct boardobjgrp *pboardobjgrp) +{ + struct boardobj *pboardobj; + u32 status = 0; + u32 stat; + u8 index; + + gk20a_dbg_info(""); + + if (pboardobjgrp->mask == NULL) + return -EINVAL; + if (pboardobjgrp->ppobjects == NULL) + return -EINVAL; + + BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) { + stat = pboardobjgrp->objremoveanddestroy(pboardobjgrp, index); + if (status == 0) + status = stat; + + pboardobjgrp->ppobjects[index] = NULL; + pboardobjgrp->objmask &= ~BIT(index); + } + + pboardobjgrp->objmask = 0; + + if (pboardobjgrp->objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) { + if (status == 0) + status = -EINVAL; + + WARN_ON(true); + } + + /* Destroy the PMU CMD data */ + stat = boardobjgrp_pmucmd_destroy_impl(&pboardobjgrp->pmu.set); + if (status == 0) + status = stat; + + stat = boardobjgrp_pmucmd_destroy_impl(&pboardobjgrp->pmu.getstatus); + if (status == 0) + status = stat; + + pboardobjgrp->bconstructed = false; + + return status; +} + +u32 boardobjgrp_pmucmd_construct_impl(struct gk20a *g, struct boardobjgrp + *pboardobjgrp, struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid, + u8 hdrsize, u8 entrysize, u16 fbsize) +{ + gk20a_dbg_info(""); + + /* Copy the parameters into the CMD*/ + cmd->id = id; + cmd->msgid = msgid; + cmd->hdrsize = hdrsize; + cmd->entrysize = entrysize; + cmd->fbsize = fbsize; + + return 0; +} + + +u32 boardobjgrp_pmucmd_destroy_impl(struct boardobjgrp_pmu_cmd *cmd) +{ + return 0; +} + +u32 boardobjgrp_pmucmd_pmuinithandle_impl(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct boardobjgrp_pmu_cmd *pcmd) +{ + u32 status = 0; + struct mem_desc *sysmem_desc = &pcmd->surf.sysmem_desc; + + gk20a_dbg_info(""); + + if (pcmd->id == BOARDOBJGRP_GRP_CMD_ID_INVALID) + goto boardobjgrp_pmucmd_pmuinithandle_exit; + + gk20a_pmu_sysmem_surface_alloc(g, sysmem_desc, pcmd->fbsize); + + pcmd->buf = (struct nv_pmu_boardobjgrp_super *)sysmem_desc->cpu_va; + +boardobjgrp_pmucmd_pmuinithandle_exit: + return status; +} + +u32 boardobjgrp_pmuinithandle_impl(struct gk20a *g, + struct boardobjgrp *pboardobjgrp) +{ + u32 status = 0; + + gk20a_dbg_info(""); + + status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp, + &pboardobjgrp->pmu.set); + if (status) { + gk20a_err(dev_from_gk20a(g), "failed to init pmu set cmd"); + goto boardobjgrp_pmuinithandle_exit; + } + + status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp, + &pboardobjgrp->pmu.getstatus); + if (status) { + gk20a_err(dev_from_gk20a(g), "failed to init get status command"); + goto boardobjgrp_pmuinithandle_exit; + } + + /* If the GRP_SET CMD has not been allocated, nothing left to do. */ + if (((pboardobjgrp->pmu.set.id) == BOARDOBJGRP_GRP_CMD_ID_INVALID) || + (BOARDOBJGRP_IS_EMPTY(pboardobjgrp))) + goto boardobjgrp_pmuinithandle_exit; + + /* Send the BOARDOBJGRP to the pmu via RM_PMU_BOARDOBJ_CMD_GRP. */ + status = pboardobjgrp->pmuset(g, pboardobjgrp); + if (status) + gk20a_err(dev_from_gk20a(g), "failed to send boardobg grp to PMU"); + +boardobjgrp_pmuinithandle_exit: + return status; +} + + +u32 boardobjgrp_pmuhdrdatainit_super(struct gk20a *g, struct boardobjgrp + *pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu, + struct boardobjgrpmask *mask) +{ + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + if (pboardobjgrppmu == NULL) + return -EINVAL; + pboardobjgrppmu->type = pboardobjgrp->type; + pboardobjgrppmu->class_id = pboardobjgrp->classid; + pboardobjgrppmu->obj_slots = BOARDOBJGRP_PMU_SLOTS_GET(pboardobjgrp); + + gk20a_dbg_info(" Done"); + return 0; +} + +u32 boardobjgrp_pmudatainstget_stub(struct gk20a *g, + struct nv_pmu_boardobjgrp *boardobjgrppmu, + struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx) +{ + gk20a_dbg_info(""); + return -EINVAL; +} + + +u32 boardobjgrp_pmustatusinstget_stub(struct gk20a *g, void *pboardobjgrppmu, + struct nv_pmu_boardobj_query **ppBoardobjpmustatus, u8 idx) +{ + gk20a_dbg_info(""); + return -EINVAL; +} + + +u32 boardobjgrp_pmudatainit_super(struct gk20a *g, struct boardobjgrp + *pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) +{ + u32 status = 0; + struct boardobj *pboardobj = NULL; + struct nv_pmu_boardobj *ppmudata = NULL; + u8 index; + + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + if (pboardobjgrppmu == NULL) + return -EINVAL; + + /* Initialize the PMU HDR data.*/ + status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp, pboardobjgrppmu, + pboardobjgrp->mask); + if (status) { + gk20a_err(dev_from_gk20a(g), + "unable to init boardobjgrp pmuhdr data"); + goto boardobjgrppmudatainit_super_done; + } + + BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) { + status = pboardobjgrp->pmudatainstget(g, + (struct nv_pmu_boardobjgrp *)pboardobjgrppmu, + &ppmudata, index); + if (status) { + gk20a_err(dev_from_gk20a(g), + "could not get object instance"); + goto boardobjgrppmudatainit_super_done; + } + + /* Initialize the PMU Data and send to PMU */ + status = pboardobj->pmudatainit(g, pboardobj, ppmudata); + if (status) { + gk20a_err(dev_from_gk20a(g), + "could not parse pmu for device %d", index); + goto boardobjgrppmudatainit_super_done; + } + } + +boardobjgrppmudatainit_super_done: + gk20a_dbg_info(" Done"); + return status; +} + +u32 boardobjgrp_pmuset_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp) +{ + u32 status = 0; + + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + + if (!pboardobjgrp->bconstructed) + return -EINVAL; + + if (pboardobjgrp->pmu.unitid == BOARDOBJGRP_UNIT_ID_INVALID) + return -EINVAL; + + if (pboardobjgrp->pmu.classid == BOARDOBJGRP_GRP_CLASS_ID_INVALID) + return -EINVAL; + + if (pboardobjgrp->pmu.set.id == BOARDOBJGRP_GRP_CMD_ID_INVALID) + return -EINVAL; + + if ((pboardobjgrp->pmu.set.hdrsize == 0) || + (pboardobjgrp->pmu.set.entrysize == 0) || + (pboardobjgrp->pmu.set.buf == NULL)) + return -EINVAL; + + /* If no objects in the group, return early */ + if (BOARDOBJGRP_IS_EMPTY(pboardobjgrp)) + return -EINVAL; + + /* Initialize PMU buffer with BOARDOBJGRP data. */ + memset(pboardobjgrp->pmu.set.buf, 0x0, pboardobjgrp->pmu.set.fbsize); + status = pboardobjgrp->pmudatainit(g, pboardobjgrp, + pboardobjgrp->pmu.set.buf); + if (status) { + gk20a_err(dev_from_gk20a(g), + "could not parse pmu data"); + goto boardobjgrp_pmuset_exit; + } + + /* + * Reset the boolean that indicates set status for most recent + * instance of BOARDOBJGRP. + */ + pboardobjgrp->pmu.bset = false; + + /* Send the SET PMU CMD to the PMU */ + status = boardobjgrp_pmucmdsend(g, pboardobjgrp, + &pboardobjgrp->pmu.set); + if (status) { + gk20a_err(dev_from_gk20a(g), "could not send SET CMD to PMU"); + goto boardobjgrp_pmuset_exit; + } + + pboardobjgrp->pmu.bset = true; + +boardobjgrp_pmuset_exit: + return status; +} + +u32 +boardobjgrp_pmugetstatus_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp, + struct boardobjgrpmask *mask) +{ + u32 status = 0; + + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + + if (!pboardobjgrp->bconstructed) + return -EINVAL; + + if (pboardobjgrp->pmu.unitid == BOARDOBJGRP_UNIT_ID_INVALID) + return -EINVAL; + + if (pboardobjgrp->pmu.classid == BOARDOBJGRP_GRP_CLASS_ID_INVALID) + return -EINVAL; + + if (pboardobjgrp->pmu.set.id == BOARDOBJGRP_GRP_CMD_ID_INVALID) + return -EINVAL; + + if ((pboardobjgrp->pmu.set.hdrsize == 0) || + (pboardobjgrp->pmu.set.entrysize == 0) || + (pboardobjgrp->pmu.set.buf == NULL)) + return -EINVAL; + + /* If no objects in the group, return early */ + if (BOARDOBJGRP_IS_EMPTY(pboardobjgrp)) + return -EINVAL; + + /* + * Can only GET_STATUS if the BOARDOBJGRP has been previously SET to the + * PMU + */ + if (!pboardobjgrp->pmu.bset) + return -EINVAL; + + /* + * Initialize PMU buffer with the mask of BOARDOBJGRPs for which to + * retrieve status + */ + + memset(pboardobjgrp->pmu.getstatus.buf, 0x0, + pboardobjgrp->pmu.getstatus.fbsize); + status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp, + pboardobjgrp->pmu.getstatus.buf, mask); + if (status) { + gk20a_err(dev_from_gk20a(g), "could not init PMU HDR data"); + goto boardobjgrp_pmugetstatus_exit; + } + + /* Send the GET_STATUS PMU CMD to the PMU */ + status = boardobjgrp_pmucmdsend(g, pboardobjgrp, + &pboardobjgrp->pmu.getstatus); + if (status) { + gk20a_err(dev_from_gk20a(g), + "could not send GET_STATUS cmd to PMU"); + goto boardobjgrp_pmugetstatus_exit; + } + +boardobjgrp_pmugetstatus_exit: + return status; +} + +static u32 +boardobjgrp_objinsert_final(struct boardobjgrp *pboardobjgrp, + struct boardobj *pboardobj, u8 index) +{ + + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + + if (pboardobj == NULL) + return -EINVAL; + + if (index > pboardobjgrp->objslots) + return -EINVAL; + + if (pboardobjgrp->ppobjects[index] != NULL) + return -EINVAL; + + /* + * Check that this BOARDOBJ has not already been added to a + * BOARDOBJGRP + */ + if (pboardobj->idx != CTRL_BOARDOBJ_IDX_INVALID) + return -EINVAL; + + pboardobjgrp->ppobjects[index] = pboardobj; + pboardobjgrp->objmaxidx = BOARDOBJGRP_IS_EMPTY(pboardobjgrp) ? + index : max(pboardobjgrp->objmaxidx, index); + pboardobj->idx = index; + + pboardobjgrp->objmask |= BIT(index); + + gk20a_dbg_info(" Done"); + + return boardobjgrpmask_bitset(pboardobjgrp->mask, index); +} + +static struct boardobj *boardobjgrp_objgetbyidx_final( + struct boardobjgrp *pboardobjgrp, u8 index) +{ + if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) + return NULL; + return pboardobjgrp->ppobjects[index]; +} + +static struct boardobj *boardobjgrp_objgetnext_final( + struct boardobjgrp *pboardobjgrp, u8 *currentindex, + struct boardobjgrpmask *mask) +{ + struct boardobj *pboardobjnext = NULL; + u8 objmaxidx; + u8 index; + + if (currentindex == NULL) + return NULL; + + if (pboardobjgrp == NULL) + return NULL; + + /* Search from next element unless first object was requested */ + index = (*currentindex != CTRL_BOARDOBJ_IDX_INVALID) ? + (*currentindex + 1) : 0; + + /* For the cases below in which we have to return NULL */ + *currentindex = CTRL_BOARDOBJ_IDX_INVALID; + + + /* Validate provided mask */ + if (mask != NULL) { + if (!(boardobjgrpmask_sizeeq(pboardobjgrp->mask, mask))) + return NULL; + } + + objmaxidx = pboardobjgrp->objmaxidx; + + if (objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) { + for (; index <= objmaxidx; index++) { + pboardobjnext = pboardobjgrp->ppobjects[index]; + if (pboardobjnext != NULL) { + /* Filter results using client provided mask.*/ + if (mask != NULL) { + if (!boardobjgrpmask_bitget(mask, + index)) { + pboardobjnext = NULL; + continue; + } + } + *currentindex = index; + break; + } + } + } + + return pboardobjnext; +} + +static u32 boardobjgrp_objremoveanddestroy_final( + struct boardobjgrp *pboardobjgrp, + u8 index) +{ + u32 status = 0; + u32 stat; + + gk20a_dbg_info(""); + + if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) + return -EINVAL; + + if (pboardobjgrp->objmaxidx == CTRL_BOARDOBJ_IDX_INVALID) + return -EINVAL; + + status = pboardobjgrp->ppobjects[index]->destruct( + pboardobjgrp->ppobjects[index]); + + pboardobjgrp->ppobjects[index] = NULL; + + pboardobjgrp->objmask &= ~BIT(index); + + stat = boardobjgrpmask_bitclr(pboardobjgrp->mask, index); + if (stat) { + if (status == 0) + status = stat; + } + + /* objmaxidx requires update only if that very object was removed */ + if (pboardobjgrp->objmaxidx == index) { + pboardobjgrp->objmaxidx = + boardobjgrpmask_bitidxhighest(pboardobjgrp->mask); + } + + return status; +} + +void boardobjgrpe32hdrset(struct nv_pmu_boardobjgrp *hdr, u32 objmask) +{ + u32 slots = objmask; + + gk20a_dbg_info(""); + + HIGHESTBITIDX_32(slots); + slots++; + + hdr->super.type = CTRL_BOARDOBJGRP_TYPE_E32; + hdr->super.class_id = 0; + hdr->super.obj_slots = (u8)slots; + hdr->obj_mask = objmask; +} + +static void boardobjgrp_pmucmdhandler(struct gk20a *g, struct pmu_msg *msg, + void *param, u32 handle, u32 status) +{ + struct nv_pmu_boardobj_msg_grp *pgrpmsg; + struct boardobjgrp_pmucmdhandler_params *phandlerparams = + (struct boardobjgrp_pmucmdhandler_params *)param; + struct boardobjgrp *pboardobjgrp = phandlerparams->pboardobjgrp; + struct boardobjgrp_pmu_cmd *pgrpcmd = phandlerparams->pcmd; + + gk20a_dbg_info(""); + + pgrpmsg = &msg->msg.boardobj.grp; + + if (pgrpmsg->class_id != pboardobjgrp->pmu.classid) { + gk20a_err(dev_from_gk20a(g), + "Unrecognized GRP type: unit %x class id=0x%02x cmd id %x", + msg->hdr.unit_id, pboardobjgrp->pmu.classid, + pgrpcmd->id); + return; + } + + if (msg->msg.boardobj.msg_type != pgrpcmd->msgid) { + gk20a_err(dev_from_gk20a(g), + "unsupported msg for unit %x class %x cmd id %x msg %x", + msg->hdr.unit_id, pboardobjgrp->pmu.classid, + pgrpcmd->id, msg->msg.boardobj.msg_type); + return; + } + + if (msg->msg.boardobj.grp_set.flcn_status != 0) { + gk20a_err(dev_from_gk20a(g), + "cmd abort for unit %x class %x cmd id %x status %x", + msg->hdr.unit_id, pboardobjgrp->pmu.classid, + pgrpcmd->id, + msg->msg.boardobj.grp_set.flcn_status); + return; + } + + phandlerparams->success = pgrpmsg->b_success ? 1 : 0; + + if (!pgrpmsg->b_success) { + gk20a_err(dev_from_gk20a(g), + "failed GRPCMD: msgtype=0x%x, classid=0x%x, cmd id %x", + pgrpmsg->msg_type, pgrpmsg->class_id, + pgrpcmd->id); + return; + } +} + +static u32 boardobjgrp_pmucmdsend(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct boardobjgrp_pmu_cmd *pcmd) +{ + struct boardobjgrp_pmucmdhandler_params handlerparams = { 0 }; + struct pmu_payload payload = { {0} }; + struct nv_pmu_boardobj_cmd_grp *pgrpcmd; + struct pmu_cmd cmd; + u32 seqdesc; + u32 status = 0; + + gk20a_dbg_info(""); + + memset(&cmd, 0, sizeof(struct pmu_cmd)); + cmd.hdr.unit_id = pboardobjgrp->pmu.unitid; + cmd.hdr.size = sizeof(struct nv_pmu_boardobj_cmd_grp) + + sizeof(struct pmu_hdr); + + pgrpcmd = &cmd.cmd.boardobj.grp; + pgrpcmd->cmd_type = pcmd->id; + pgrpcmd->class_id = pboardobjgrp->pmu.classid; + pgrpcmd->grp.hdr_size = pcmd->hdrsize; + pgrpcmd->grp.entry_size = pcmd->entrysize; + + /* + * alloc mem in vidmem & copy constructed pmu boardobjgrp data from + * sysmem to vidmem + */ + gk20a_pmu_vidmem_surface_alloc(g, &pcmd->surf.vidmem_desc, + pcmd->fbsize); + gk20a_pmu_surface_describe(g, &pcmd->surf.vidmem_desc, + &pgrpcmd->grp.fb); + gk20a_mem_wr_n(g, &pcmd->surf.vidmem_desc, 0, pcmd->buf, pcmd->fbsize); + + /* + * PMU reads command from sysmem so assigned + * "payload.in.buf = pcmd->buf" + * but PMU access pmu boardobjgrp data from vidmem copied above + */ + payload.in.buf = pcmd->buf; + payload.in.size = max(pcmd->hdrsize, pcmd->entrysize); + payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; + payload.in.offset = offsetof(struct nv_pmu_boardobj_cmd_grp, grp); + + /* Setup the handler params to communicate back results.*/ + handlerparams.pboardobjgrp = pboardobjgrp; + handlerparams.pcmd = pcmd; + handlerparams.success = 0; + + status = gk20a_pmu_cmd_post(g, &cmd, NULL, &payload, + PMU_COMMAND_QUEUE_LPQ, + boardobjgrp_pmucmdhandler, + (void *)&handlerparams, + &seqdesc, ~0); + if (status) { + gk20a_err(dev_from_gk20a(g), + "unable to post boardobj grp cmd for unit %x cmd id %x", + cmd.hdr.unit_id, pcmd->id); + goto boardobjgrp_pmucmdsend_exit; + } + pmu_wait_message_cond(&g->pmu, + gk20a_get_gr_idle_timeout(g), + &handlerparams.success, 1); + if (handlerparams.success == 0) { + gk20a_err(dev_from_gk20a(g), "could not process cmd\n"); + status = -ETIMEDOUT; + goto boardobjgrp_pmucmdsend_exit; + } + +boardobjgrp_pmucmdsend_exit: + return status; +} diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp.h b/drivers/gpu/nvgpu/boardobj/boardobjgrp.h new file mode 100644 index 00000000..e98a6cdb --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp.h @@ -0,0 +1,390 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ + +#ifndef _BOARDOBJGRP_H_ +#define _BOARDOBJGRP_H_ + +struct boardobjgrp; + +/* ------------------------ Includes ----------------------------------------*/ +#include +#include "gk20a/gk20a.h" +#include "gk20a/pmu_gk20a.h" +#include "ctrl/ctrlboardobj.h" +#include "boardobj.h" +#include "boardobjgrpmask.h" +#include "pmuif/gpmuifboardobj.h" + +/* +* Board Object Group destructor. +* +*/ +typedef u32 boardobjgrp_destruct(struct boardobjgrp *pboardobjgrp); + +/* +* Inserts a previously constructed Board Object into a Board Object Group for +* tracking. Objects are inserted in the array based on the given index. +*/ +typedef u32 boardobjgrp_objinsert(struct boardobjgrp *pboardobjgrp, + struct boardobj *pboardobj, u8 index); + +/* +* Retrieves a Board Object from a Board Object Group using the group's index. +* +*/ +typedef struct boardobj *boardobjgrp_objgetbyidx( + struct boardobjgrp *pBobrdobjgrp, u8 index); + +/* +* Retrieve Board Object immediately following one pointed by @ref pcurrentindex +* filtered out by the provided mask. If (pMask == NULL) => no filtering. +*/ +typedef struct boardobj *boardobjgrp_objgetnext( + struct boardobjgrp *pboardobjgrp, + u8 *currentindex, struct boardobjgrpmask *mask); + +/* +* Board Object Group Remover and destructor. This is used to remove and +* destruct specific entry from the Board Object Group. +*/ +typedef u32 boardobjgrp_objremoveanddestroy(struct boardobjgrp *pboardobjgrp, + u8 index); + +/* +* BOARDOBJGRP handler for PMU_UNIT_INIT. Calls the PMU_UNIT_INIT handlers +* for the constructed PMU CMDs, and then sets the object via the +* PMU_BOARDOBJ_CMD_GRP interface (if constructed). +*/ +typedef u32 boardobjgrp_pmuinithandle(struct gk20a *g, + struct boardobjgrp *pboardobjGrp); + +/* +* Fills out the appropriate the PMU_BOARDOBJGRP_ driver<->PMU description +* header structure, more specifically a mask of BOARDOBJs. +*/ +typedef u32 boardobjgrp_pmuhdrdatainit(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct nv_pmu_boardobjgrp_super *pboardobjgrppmu, + struct boardobjgrpmask *mask); + +/* +* Fills out the appropriate the PMU_BOARDOBJGRP_ driver->PMU description +* structure, describing the BOARDOBJGRP and all of its BOARDOBJs to the PMU. +*/ +typedef u32 boardobjgrp_pmudatainit(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct nv_pmu_boardobjgrp_super *pboardobjgrppmu); + +/* +* Sends a BOARDOBJGRP to the PMU via the PMU_BOARDOBJ_CMD_GRP interface. +* This interface leverages @ref boardobjgrp_pmudatainit to populate the +* structure. +*/ +typedef u32 boardobjgrp_pmuset(struct gk20a *g, + struct boardobjgrp *pboardobjgrp); + +/* +* Gets the dynamic status of the PMU BOARDOBJGRP via the +* PMU_BOARDOBJ_CMD_GRP GET_STATUS interface. +*/ +typedef u32 boardobjgrp_pmugetstatus(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct boardobjgrpmask *mask); + +typedef u32 boardobjgrp_pmudatainstget(struct gk20a *g, + struct nv_pmu_boardobjgrp *boardobjgrppmu, + struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx); + +typedef u32 boardobjgrp_pmustatusinstget(struct gk20a *g, void *pboardobjgrppmu, + struct nv_pmu_boardobj_query **ppBoardobjpmustatus, u8 idx); + +/* +* Structure describing an PMU CMD for interacting with the representaition +* of this BOARDOBJGRP within the PMU. +*/ +struct boardobjgrp_pmu_cmd { + u8 id; + u8 msgid; + u8 hdrsize; + u8 entrysize; + u16 fbsize; + struct nv_pmu_boardobjgrp_super *buf; + struct pmu_surface surf; +}; + +/* +* Structure of state describing how to communicate with representation of this +* BOARDOBJGRP in the PMU. +*/ +struct boardobjgrp_pmu { + u8 unitid; + u8 classid; + bool bset; + struct boardobjgrp_pmu_cmd set; + struct boardobjgrp_pmu_cmd getstatus; +}; + +/* +* Function by which a class which implements BOARDOBJGRP can construct a PMU +* CMD. This provides the various information describing the PMU CMD including +* the CMD and MSG ID and the size of the various sturctures in the payload. +*/ +typedef u32 boardobjgrp_pmucmd_construct(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid, + u8 hdrsize, u8 entrysize, u16 fbsize); + +/* +* Destroys BOARDOBJGRP PMU SW state. CMD. +*/ +typedef u32 boardobjgrp_pmucmd_destroy(struct boardobjgrp_pmu_cmd *cmd); + +/* +* init handler for the BOARDOBJGRP PMU CMD. Allocates and maps the +* PMU CMD payload within both the PMU and driver so that it can be referenced +* at run-time. +*/ +typedef u32 boardobjgrp_pmucmd_pmuinithandle(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct boardobjgrp_pmu_cmd *cmd); + +/* +* Base Class Group for all physical or logical device on the PCB. +* Contains fields common to all devices on the board. Specific types of +* devices groups may extend this object adding any details specific to that +* device group or device-type. +*/ +struct boardobjgrp { + u32 objmask; + bool bconstructed; + u8 type; + u8 classid; + struct boardobj **ppobjects; + struct boardobjgrpmask *mask; + u8 objslots; + u8 objmaxidx; + struct boardobjgrp_pmu pmu; + + /* Basic interfaces */ + boardobjgrp_destruct *destruct; + boardobjgrp_objinsert *objinsert; + boardobjgrp_objgetbyidx *objgetbyidx; + boardobjgrp_objgetnext *objgetnext; + boardobjgrp_objremoveanddestroy *objremoveanddestroy; + + /* PMU interfaces */ + boardobjgrp_pmuinithandle *pmuinithandle; + boardobjgrp_pmuhdrdatainit *pmuhdrdatainit; + boardobjgrp_pmudatainit *pmudatainit; + boardobjgrp_pmuset *pmuset; + boardobjgrp_pmugetstatus *pmugetstatus; + + boardobjgrp_pmudatainstget *pmudatainstget; + boardobjgrp_pmustatusinstget *pmustatusinstget; +}; + +/* +* Macro test whether a specified index into the BOARDOBJGRP is valid. +* +*/ +#define boardobjgrp_idxisvalid(_pboardobjgrp, _idx) \ + (((_idx) < (_pboardobjgrp)->objslots) && \ + ((_pboardobjgrp)->ppobjects[(_idx)] != NULL)) + +/* +* Macro test whether a specified BOARDOBJGRP is empty. +*/ +#define BOARDOBJGRP_IS_EMPTY(_pboardobjgrp) \ + ((!((_pboardobjgrp)->bconstructed)) || \ + ((_pboardobjgrp)->objmaxidx == CTRL_BOARDOBJ_IDX_INVALID)) + +#define boardobjgrp_objinsert(_pboardobjgrp, _pboardobj, _idx) \ + ((_pboardobjgrp)->objinsert((_pboardobjgrp), (_pboardobj), (_idx))) + +/* +* Helper macro to determine the "next" open/empty index after all allocated +* objects. This is intended to be used to find the index at which objects can +* be inserted contiguously (i.e. w/o fear of colliding with existing objects). +*/ +#define BOARDOBJGRP_NEXT_EMPTY_IDX(_pboardobjgrp) \ + ((CTRL_BOARDOBJ_IDX_INVALID == (_pboardobjgrp)->objmaxidx) ? 0 : \ + ((((_pboardobjgrp)->objmaxidx + 1) >= (_pboardobjgrp)->objslots) ? \ + (u8)CTRL_BOARDOBJ_IDX_INVALID : (u8)((_pboardobjgrp)->objmaxidx + 1))) + +/* +* Helper macro to determine the number of @ref BOARDOBJ pointers +* that are required to be allocated in PMU @ref ppObjects. +*/ +#define BOARDOBJGRP_PMU_SLOTS_GET(_pboardobjgrp) \ + ((CTRL_BOARDOBJ_IDX_INVALID == (_pboardobjgrp)->objmaxidx) ? 0 : \ + (u8)((_pboardobjgrp)->objmaxidx + 1)) + +#define BOARDOBJGRP_OBJ_GET_BY_IDX(_pboardobjgrp, _idx) \ + ((_pboardobjgrp)->objgetbyidx((_pboardobjgrp), (_idx))) + +/* +* macro to look-up next object while tolerating error if +* Board Object Group is not constructed. +*/ + +#define boardobjgrpobjgetnextsafe(_pgrp, _pindex, _pmask) \ + ((_pgrp)->bconstructed ? \ + (_pgrp)->objgetnext((_pgrp), (_pindex), (_pmask)) : NULL) + +/* +* Used to traverse all Board Objects stored within @ref _pgrp in the increasing +* index order. +* If @ref _pmask is provided only objects specified by the mask are traversed. +*/ +#define BOARDOBJGRP_ITERATOR(_pgrp, _ptype, _pobj, _index, _pmask) \ + for (_index = CTRL_BOARDOBJ_IDX_INVALID, \ + _pobj = (_ptype)boardobjgrpobjgetnextsafe((_pgrp), &_index, (_pmask));\ + _pobj != NULL; \ + _pobj = (_ptype)boardobjgrpobjgetnextsafe((_pgrp), &_index, (_pmask))) +#define BOARDOBJGRP_FOR_EACH(_pgrp, _ptype, _pobj, _index) \ + BOARDOBJGRP_ITERATOR(_pgrp, _ptype, _pobj, _index, NULL) + +/*! +* Invalid UNIT_ID. Used to indicate that the implementing class has not set +* @ref BOARDOBJGRP::unitId and, thus, certain BOARDOBJGRP PMU interfaces are +* not supported. +*/ +#define BOARDOBJGRP_UNIT_ID_INVALID 255 + +/*! +* Invalid UNIT_ID. Used to indicate that the implementing class has not set +* @ref BOARDOBJGRP::grpType and, thus, certain BOARDOBJGRP PMU interfaces are +* not supported. +*/ +#define BOARDOBJGRP_GRP_CLASS_ID_INVALID 255 + +/*! +* Invalid UNIT_ID. Used to indicate that the implementing class has not set +* @ref BOARDOBJGRP::grpSetCmdId and, thus, certain BOARDOBJGRP PMU interfaces +* are not supported. +*/ +#define BOARDOBJGRP_GRP_CMD_ID_INVALID 255 + +/*! +* Helper macro to construct a BOARDOBJGRP's PMU SW state. +* +* @param[out] pboardobjgrp BOARDOBJGRP pointer +* @param[in] _eng +* Implementing engine/unit which manages the BOARDOBJGRP. +* @param[in] _class +* Class ID of BOARDOBJGRP. +*/ +#define BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, _ENG, _CLASS) \ +do { \ + (pboardobjgrp)->pmu.unitid = PMU_UNIT_##_ENG; \ + (pboardobjgrp)->pmu.classid = \ + NV_PMU_##_ENG##_BOARDOBJGRP_CLASS_ID_##_CLASS; \ +} while (0) + +#define BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(pgpu, pboardobjgrp, eng, ENG, \ + class, CLASS) \ + boardobjgrp_pmucmd_construct_impl( \ + pgpu, /* pgpu */ \ + pboardobjgrp, /* pboardobjgrp */ \ + &((pboardobjgrp)->pmu.set), /* pcmd */ \ + NV_PMU_##ENG##_CMD_ID_BOARDOBJ_GRP_SET, /* id */ \ + NV_PMU_##ENG##_MSG_ID_BOARDOBJ_GRP_SET, /* msgid */ \ + (u32)sizeof(union nv_pmu_##eng##_##class##_boardobjgrp_set_header_aligned), \ + (u32)sizeof(union nv_pmu_##eng##_##class##_boardobj_set_union_aligned), \ + (u32)sizeof(struct nv_pmu_##eng##_##class##_boardobj_grp_set)) + +#define BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(pgpu, pboardobjgrp, \ + eng, ENG, class, CLASS) \ + boardobjgrp_pmucmd_construct_impl( \ + pgpu, /* pGpu */ \ + pboardobjgrp, /* pBoardObjGrp */ \ + &((pboardobjgrp)->pmu.getstatus), /* pCmd */ \ + NV_PMU_##ENG##_CMD_ID_BOARDOBJ_GRP_GET_STATUS, /* id */ \ + NV_PMU_##ENG##_MSG_ID_BOARDOBJ_GRP_SET, /* msgid */ \ + (u32)sizeof(union nv_pmu_##eng##_##class##_boardobjgrp_get_status_header_aligned), \ + (u32)sizeof(union nv_pmu_##eng##_##class##_boardobj_get_status_union_aligned), \ + (u32)sizeof(struct nv_pmu_##eng##_##class##_boardobj_grp_get_status)) + +/* ------------------------ Function Prototypes ----------------------------- */ +/* Constructor and destructor */ +u32 boardobjgrp_construct_super(struct boardobjgrp *pboardobjgrp); +boardobjgrp_destruct boardobjgrp_destruct_impl; +boardobjgrp_destruct boardobjgrp_destruct_super; + +/* PMU_CMD interfaces */ +boardobjgrp_pmucmd_construct boardobjgrp_pmucmd_construct_impl; +boardobjgrp_pmucmd_destroy boardobjgrp_pmucmd_destroy_impl; +boardobjgrp_pmucmd_pmuinithandle boardobjgrp_pmucmd_pmuinithandle_impl; + +/* BOARDOBJGRP interfaces */ +boardobjgrp_pmuinithandle boardobjgrp_pmuinithandle_impl; +boardobjgrp_pmuhdrdatainit boardobjgrp_pmuhdrdatainit_super; +boardobjgrp_pmudatainit boardobjgrp_pmudatainit_super; + +boardobjgrp_pmudatainit boardobjgrp_pmudatainit_legacy; +boardobjgrp_pmuset boardobjgrp_pmuset_impl; +boardobjgrp_pmugetstatus boardobjgrp_pmugetstatus_impl; + +void boardobjgrpe32hdrset(struct nv_pmu_boardobjgrp *hdr, u32 objmask); + +/* ------------------------ Include Derived Types --------------------------- */ +#include "boardobj/boardobjgrp_e32.h" +#include "boardobj/boardobjgrp_e255.h" + +#define HIGHESTBITIDX_32(n32) \ +{ \ + u32 count = 0; \ + while (n32 >>= 1) \ + count++; \ + n32 = count; \ +} + +#define LOWESTBIT(x) ((x) & (((x)-1) ^ (x))) + +#define HIGHESTBIT(n32) \ +{ \ + HIGHESTBITIDX_32(n32); \ + n32 = NVBIT(n32); \ +} + +#define ONEBITSET(x) ((x) && (((x) & ((x)-1)) == 0)) + +#define LOWESTBITIDX_32(n32) \ +{ \ + n32 = LOWESTBIT(n32); \ + IDX_32(n32); \ +} + +#define NUMSETBITS_32(n32) \ +{ \ + n32 = n32 - ((n32 >> 1) & 0x55555555); \ + n32 = (n32 & 0x33333333) + ((n32 >> 2) & 0x33333333); \ + n32 = (((n32 + (n32 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; \ +} + +#define IDX_32(n32) \ +{ \ + u32 idx = 0; \ + if ((n32) & 0xFFFF0000) \ + idx += 16; \ + if ((n32) & 0xFF00FF00) \ + idx += 8; \ + if ((n32) & 0xF0F0F0F0) \ + idx += 4; \ + if ((n32) & 0xCCCCCCCC) \ + idx += 2; \ + if ((n32) & 0xAAAAAAAA) \ + idx += 1; \ + (n32) = idx; \ +} +#endif diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.c b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.c new file mode 100644 index 00000000..a56dca9b --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.c @@ -0,0 +1,92 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ + +#include "gk20a/gk20a.h" +#include "boardobj.h" +#include "boardobjgrp_e255.h" +#include "ctrl/ctrlboardobj.h" +#include "pmuif/gpmuifboardobj.h" +#include "boardobjgrp.h" +#include "boardobjgrpmask.h" + +u32 boardobjgrpconstruct_e255(struct boardobjgrp_e255 *pboardobjgrp_e255) +{ + u32 status = 0; + u8 objslots; + + gk20a_dbg_info(""); + + objslots = 255; + status = boardobjgrpmask_e255_init(&pboardobjgrp_e255->mask, NULL); + if (status) + goto boardobjgrpconstruct_e255_exit; + + pboardobjgrp_e255->super.type = CTRL_BOARDOBJGRP_TYPE_E255; + pboardobjgrp_e255->super.ppobjects = pboardobjgrp_e255->objects; + pboardobjgrp_e255->super.objslots = objslots; + pboardobjgrp_e255->super.mask = &(pboardobjgrp_e255->mask.super); + + status = boardobjgrp_construct_super(&pboardobjgrp_e255->super); + if (status) + goto boardobjgrpconstruct_e255_exit; + + pboardobjgrp_e255->super.destruct = boardobjgrpdestruct_e255; + + pboardobjgrp_e255->super.pmuhdrdatainit = + boardobjgrp_pmuhdrdatainit_e255; + +boardobjgrpconstruct_e255_exit: + return status; +} + +u32 boardobjgrpdestruct_e255(struct boardobjgrp *pboardobjgrp) +{ + u32 status = 0; + + gk20a_dbg_info(""); + + pboardobjgrp->mask = NULL; + pboardobjgrp->objslots = 0; + pboardobjgrp->ppobjects = NULL; + + return status; +} + +u32 boardobjgrp_pmuhdrdatainit_e255(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct nv_pmu_boardobjgrp_super *pboardobjgrppmu, + struct boardobjgrpmask *mask) +{ + struct nv_pmu_boardobjgrp_e255 *pgrpe255 = + (struct nv_pmu_boardobjgrp_e255 *)pboardobjgrppmu; + u32 status; + + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + + if (pboardobjgrppmu == NULL) + return -EINVAL; + + status = boardobjgrpmask_export(mask, + mask->bitcount, + &pgrpe255->obj_mask.super); + if (status) { + gk20a_err(dev_from_gk20a(g), "e255 init:failed export grpmask"); + return status; + } + + return boardobjgrp_pmuhdrdatainit_super(g, + pboardobjgrp, pboardobjgrppmu, mask); +} diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.h b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.h new file mode 100644 index 00000000..929517ad --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e255.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _BOARDOBJGRP_E255_H_ +#define _BOARDOBJGRP_E255_H_ + +#include +#include "gk20a/gk20a.h" +#include "gk20a/pmu_gk20a.h" +#include "ctrl/ctrlboardobj.h" +#include "boardobj.h" +#include "boardobjgrpmask.h" +#include "boardobj/boardobjgrp.h" +#include "boardobjgrp_e255.h" + +/* + * boardobjgrp_e255 is @ref BOARDOBJGRP child class allowing storage of up + * to 255 @ref BOARDOBJ object pointers with single static 255-bit mask denoting + * valid object pointers. + */ +struct boardobjgrp_e255 { + struct boardobjgrp super; + struct boardobj *objects[CTRL_BOARDOBJGRP_E255_MAX_OBJECTS]; + struct boardobjgrpmask_e255 mask; +}; + +#define boardobjgrp_pmudatainit_e255(g, pboardpbjgrp, pboardobjgrppmu) \ + boardobjgrp_pmudatainit_super(g, pboardpbjgrp, pboardobjgrppmu) + +/* Constructor and destructor */ +u32 boardobjgrpconstruct_e255(struct boardobjgrp_e255 *pboardobjgrp); +boardobjgrp_destruct boardobjgrpdestruct_e255; +boardobjgrp_pmuhdrdatainit boardobjgrp_pmuhdrdatainit_e255; + +#endif diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.c b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.c new file mode 100644 index 00000000..95610aba --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.c @@ -0,0 +1,91 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ + +#include "gk20a/gk20a.h" +#include "boardobj.h" +#include "boardobjgrp.h" +#include "boardobjgrp_e32.h" +#include "ctrl/ctrlboardobj.h" +#include "pmuif/gpmuifboardobj.h" +#include "boardobjgrpmask.h" + + +u32 boardobjgrpconstruct_e32(struct boardobjgrp_e32 *pboardobjgrp_e32) +{ + u32 status; + u8 objslots; + + gk20a_dbg_info(""); + objslots = 32; + + status = boardobjgrpmask_e32_init(&pboardobjgrp_e32->mask, NULL); + if (status) + goto boardobjgrpconstruct_e32_exit; + + pboardobjgrp_e32->super.type = CTRL_BOARDOBJGRP_TYPE_E32; + pboardobjgrp_e32->super.ppobjects = pboardobjgrp_e32->objects; + pboardobjgrp_e32->super.objslots = objslots; + pboardobjgrp_e32->super.mask = &(pboardobjgrp_e32->mask.super); + + status = boardobjgrp_construct_super(&pboardobjgrp_e32->super); + if (status) + goto boardobjgrpconstruct_e32_exit; + + pboardobjgrp_e32->super.destruct = boardobjgrpdestruct_e32; + + pboardobjgrp_e32->super.pmuhdrdatainit = boardobjgrp_pmuhdrdatainit_e32; + +boardobjgrpconstruct_e32_exit: + return status; +} + +u32 boardobjgrpdestruct_e32(struct boardobjgrp *pboardobjgrp) +{ + u32 status = 0; + + gk20a_dbg_info(""); + + pboardobjgrp->mask = NULL; + pboardobjgrp->objslots = 0; + pboardobjgrp->ppobjects = NULL; + + return status; +} + +u32 boardobjgrp_pmuhdrdatainit_e32(struct gk20a *g, + struct boardobjgrp *pboardobjgrp, + struct nv_pmu_boardobjgrp_super *pboardobjgrppmu, + struct boardobjgrpmask *mask) +{ + struct nv_pmu_boardobjgrp_e32 *pgrpe32 = + (struct nv_pmu_boardobjgrp_e32 *)pboardobjgrppmu; + u32 status; + + gk20a_dbg_info(""); + + if (pboardobjgrp == NULL) + return -EINVAL; + + if (pboardobjgrppmu == NULL) + return -EINVAL; + status = boardobjgrpmask_export(mask, + mask->bitcount, + &pgrpe32->obj_mask.super); + if (status) { + gk20a_err(dev_from_gk20a(g), "e32 init:failed export grpmask"); + return status; + } + + return boardobjgrp_pmuhdrdatainit_super(g, + pboardobjgrp, pboardobjgrppmu, mask); +} diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.h b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.h new file mode 100644 index 00000000..249d1dd6 --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp_e32.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _BOARDOBJGRP_E32_H_ +#define _BOARDOBJGRP_E32_H_ + +#include +#include "gk20a/gk20a.h" +#include "gk20a/pmu_gk20a.h" +#include "ctrl/ctrlboardobj.h" +#include "boardobj.h" +#include "boardobjgrp.h" +#include "boardobjgrpmask.h" +#include "boardobj/boardobjgrp.h" + +/* + * boardobjgrp_e32 is @ref BOARDOBJGRP child class allowing storage of up to 32 + * @ref BOARDOBJ object pointers with single static 32-bit mask denoting valid + * object pointers. + */ +struct boardobjgrp_e32 { + /* + * BOARDOBJGRP super-class. Must be first element of the structure. + */ + struct boardobjgrp super; + /* + * Statically allocated array of PBOARDOBJ-s + */ + struct boardobj *objects[CTRL_BOARDOBJGRP_E32_MAX_OBJECTS]; + + /* + * Statically allocated mask strcuture referenced by super::pMask. + */ + struct boardobjgrpmask_e32 mask; +}; + +/* + * Wrapper to the _SUPER implementation. Provided for the child classes which + * implement this interface. + */ +#define boardobjgrp_pmudatainit_e32(g, pboardpbjgrp, pboardobjgrppmu) \ + boardobjgrp_pmudatainit_super(g, pboardpbjgrp, pboardobjgrppmu) + +/* Constructor and destructor */ +u32 boardobjgrpconstruct_e32(struct boardobjgrp_e32 *pboardobjgrp); +boardobjgrp_destruct boardobjgrpdestruct_e32; +boardobjgrp_pmuhdrdatainit boardobjgrp_pmuhdrdatainit_e32; + +#endif diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrpmask.c b/drivers/gpu/nvgpu/boardobj/boardobjgrpmask.c new file mode 100644 index 00000000..47914038 --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrpmask.c @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#include "gk20a/gk20a.h" +#include "boardobjgrp.h" +#include "ctrl/ctrlboardobj.h" + +/* +* Assures that unused bits (size .. (maskDataCount * 32 - 1)) are always zero. +*/ +#define BOARDOBJGRPMASK_NORMALIZE(_pmask) \ + ((_pmask)->data[(_pmask)->maskdatacount-1] &= (_pmask)->lastmaskfilter) + +u32 boardobjgrpmask_init(struct boardobjgrpmask *mask, u8 bitsize, + struct ctrl_boardobjgrp_mask *extmask) +{ + if (mask == NULL) + return -EINVAL; + if ((bitsize != CTRL_BOARDOBJGRP_E32_MAX_OBJECTS) && + (bitsize != CTRL_BOARDOBJGRP_E255_MAX_OBJECTS)) + return -EINVAL; + + mask->bitcount = bitsize; + mask->maskdatacount = CTRL_BOARDOBJGRP_MASK_DATA_SIZE(bitsize); + mask->lastmaskfilter = bitsize % + CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_BIT_SIZE; + + mask->lastmaskfilter = (mask->lastmaskfilter == 0) ? + 0xFFFFFFFF : (u32)(BIT(mask->lastmaskfilter) - 1); + + return (extmask == NULL) ? + boardobjgrpmask_clr(mask) : + boardobjgrpmask_import(mask, bitsize, extmask); +} + +u32 boardobjgrpmask_import(struct boardobjgrpmask *mask, u8 bitsize, + struct ctrl_boardobjgrp_mask *extmask) +{ + u8 index; + + if (mask == NULL) + return -EINVAL; + if (extmask == NULL) + return -EINVAL; + if (mask->bitcount != bitsize) + return -EINVAL; + + for (index = 0; index < mask->maskdatacount; index++) + mask->data[index] = extmask->data[index]; + + BOARDOBJGRPMASK_NORMALIZE(mask); + + return 0; +} + +u32 boardobjgrpmask_export(struct boardobjgrpmask *mask, u8 bitsize, + struct ctrl_boardobjgrp_mask *extmask) +{ + u8 index; + + if (mask == NULL) + return -EINVAL; + if (extmask == NULL) + return -EINVAL; + if (mask->bitcount != bitsize) + return -EINVAL; + + for (index = 0; index < mask->maskdatacount; index++) + extmask->data[index] = mask->data[index]; + + return 0; +} + +u32 boardobjgrpmask_clr(struct boardobjgrpmask *mask) +{ + u8 index; + + if (mask == NULL) + return -EINVAL; + for (index = 0; index < mask->maskdatacount; index++) + mask->data[index] = 0; + + return 0; +} + +u32 boardobjgrpmask_set(struct boardobjgrpmask *mask) +{ + u8 index; + + if (mask == NULL) + return -EINVAL; + for (index = 0; index < mask->maskdatacount; index++) + mask->data[index] = 0xFFFFFFFF; + BOARDOBJGRPMASK_NORMALIZE(mask); + return 0; +} + +u32 boardobjgrpmask_inv(struct boardobjgrpmask *mask) +{ + u8 index; + + if (mask == NULL) + return -EINVAL; + for (index = 0; index < mask->maskdatacount; index++) + mask->data[index] = ~mask->data[index]; + BOARDOBJGRPMASK_NORMALIZE(mask); + return 0; +} + +bool boardobjgrpmask_iszero(struct boardobjgrpmask *mask) +{ + u8 index; + + if (mask == NULL) + return true; + for (index = 0; index < mask->maskdatacount; index++) { + if (mask->data[index] != 0) + return false; + } + return true; +} + +u8 boardobjgrpmask_bitsetcount(struct boardobjgrpmask *mask) +{ + u8 index; + u8 result = 0; + + if (mask == NULL) + return result; + + for (index = 0; index < mask->maskdatacount; index++) { + u32 m = mask->data[index]; + + NUMSETBITS_32(m); + result += (u8)m; + } + + return result; +} + +u8 boardobjgrpmask_bitidxlowest(struct boardobjgrpmask *mask) +{ + u8 index; + u8 result = CTRL_BOARDOBJ_IDX_INVALID; + + if (mask == NULL) + return result; + + for (index = 0; index < mask->maskdatacount; index++) { + u32 m = mask->data[index]; + + if (m != 0) { + LOWESTBITIDX_32(m); + result = (u8)m + index * + CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_BIT_SIZE; + break; + } + } + + return result; +} + +u8 boardobjgrpmask_bitidxhighest(struct boardobjgrpmask *mask) +{ + u8 index; + u8 result = CTRL_BOARDOBJ_IDX_INVALID; + + if (mask == NULL) + return result; + + for (index = 0; index < mask->maskdatacount; index++) { + u32 m = mask->data[index]; + + if (m != 0) { + HIGHESTBITIDX_32(m); + result = (u8)m + index * + CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_BIT_SIZE; + break; + } + } + + return result; +} + +u32 boardobjgrpmask_bitclr(struct boardobjgrpmask *mask, u8 bitidx) +{ + u8 index; + u8 offset; + + if (mask == NULL) + return -EINVAL; + if (bitidx >= mask->bitcount) + return -EINVAL; + + index = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_INDEX(bitidx); + offset = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_OFFSET(bitidx); + + mask->data[index] &= ~BIT(offset); + + return 0; +} + +u32 boardobjgrpmask_bitset(struct boardobjgrpmask *mask, u8 bitidx) +{ + u8 index; + u8 offset; + + if (mask == NULL) + return -EINVAL; + if (bitidx >= mask->bitcount) + return -EINVAL; + + index = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_INDEX(bitidx); + offset = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_OFFSET(bitidx); + + mask->data[index] |= BIT(offset); + + return 0; +} + +u32 boardobjgrpmask_bitinv(struct boardobjgrpmask *mask, u8 bitidx) +{ + u8 index; + u8 offset; + + if (mask == NULL) + return -EINVAL; + if (bitidx >= mask->bitcount) + return -EINVAL; + + index = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_INDEX(bitidx); + offset = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_OFFSET(bitidx); + + mask->data[index] ^= ~BIT(offset); + + return 0; +} + +bool boardobjgrpmask_bitget(struct boardobjgrpmask *mask, u8 bitidx) +{ + u8 index; + u8 offset; + + if (mask == NULL) + return false; + if (bitidx >= mask->bitcount) + return false; + + index = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_INDEX(bitidx); + offset = CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_OFFSET(bitidx); + + return (mask->data[index] & BIT(offset)) != 0; +} + +u32 boardobjgrpmask_and(struct boardobjgrpmask *dst, + struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2) +{ + u8 index; + + if (!boardobjgrpmask_sizeeq(dst, op1)) + return -EINVAL; + if (!boardobjgrpmask_sizeeq(dst, op2)) + return -EINVAL; + + for (index = 0; index < dst->maskdatacount; index++) + dst->data[index] = op1->data[index] & op2->data[index]; + + return 0; +} + +u32 boardobjgrpmask_or(struct boardobjgrpmask *dst, + struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2) +{ + u8 index; + + if (!boardobjgrpmask_sizeeq(dst, op1)) + return -EINVAL; + if (!boardobjgrpmask_sizeeq(dst, op2)) + return -EINVAL; + + for (index = 0; index < dst->maskdatacount; index++) + dst->data[index] = op1->data[index] | op2->data[index]; + + return 0; +} + +u32 boardobjgrpmask_xor(struct boardobjgrpmask *dst, + struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2) +{ + u8 index; + + if (!boardobjgrpmask_sizeeq(dst, op1)) + return -EINVAL; + if (!boardobjgrpmask_sizeeq(dst, op2)) + return -EINVAL; + + for (index = 0; index < dst->maskdatacount; index++) + dst->data[index] = op1->data[index] ^ op2->data[index]; + + return 0; +} + +u32 boardobjgrpmask_copy(struct boardobjgrpmask *dst, + struct boardobjgrpmask *src) +{ + u8 index; + + if (!boardobjgrpmask_sizeeq(dst, src)) + return -EINVAL; + + for (index = 0; index < dst->maskdatacount; index++) + dst->data[index] = src->data[index]; + + return 0; +} + +bool boardobjgrpmask_sizeeq(struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2) +{ + if (op1 == NULL) + return false; + if (op2 == NULL) + return false; + + return op1->bitcount == op2->bitcount; +} + +bool boardobjgrpmask_issubset(struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2) +{ + u8 index; + + if (!boardobjgrpmask_sizeeq(op2, op1)) + return false; + + for (index = 0; index < op1->maskdatacount; index++) { + u32 op_1 = op1->data[index]; + u32 op_2 = op2->data[index]; + + if ((op_1 & op_2) != op_1) + return false; + } + + return true; +} diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrpmask.h b/drivers/gpu/nvgpu/boardobj/boardobjgrpmask.h new file mode 100644 index 00000000..c601d9d2 --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrpmask.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _BOARDOBJGRPMASK_H_ +#define _BOARDOBJGRPMASK_H_ + +#include "ctrl/ctrlboardobj.h" + + +/* +* Board Object Group Mask super-structure. +* Used to unify access to all BOARDOBJGRPMASK_E** child classes +*/ +struct boardobjgrpmask { + /* Number of bits supported by the mask */ + u8 bitcount; + /* Number of 32-bit words required to store all @ref bitCount bits */ + u8 maskdatacount; + /* + * Bit-mask of used-bits within last 32-bit word. Used to + * normalize data + */ + u32 lastmaskfilter; + /* + * Start of the array of 32-bit words representing the bit-mask + * Must be the last element of the structure. + */ + u32 data[CTRL_BOARDOBJGRP_MASK_ARRAY_START_SIZE]; +}; + +struct boardobjgrpmask_e32 { + /* + * BOARDOBJGRPMASK super-class. Must be the first element of the + * structure. + */ + struct boardobjgrpmask super; + /*u32 data_e32[1]; */ +}; + +struct boardobjgrpmask_e255 { + /* + * BOARDOBJGRPMASK super-class. Must be the first element of the + * structure. + */ + struct boardobjgrpmask super; + u32 data_e255[254]; +}; + +/* Init and I/O operations.*/ +u32 boardobjgrpmask_init(struct boardobjgrpmask *mask, u8 bitsize, + struct ctrl_boardobjgrp_mask *extmask); +u32 boardobjgrpmask_import(struct boardobjgrpmask *mask, u8 bitsize, + struct ctrl_boardobjgrp_mask *extmask); +u32 boardobjgrpmask_export(struct boardobjgrpmask *mask, u8 bitsize, + struct ctrl_boardobjgrp_mask *extmask); + +/* Operations on all bits of a single mask.*/ +u32 boardobjgrpmask_clr(struct boardobjgrpmask *mask); +u32 boardobjgrpmask_set(struct boardobjgrpmask *mask); +u32 boardobjgrpmask_inv(struct boardobjgrpmask *mask); +bool boardobjgrpmask_iszero(struct boardobjgrpmask *mask); +u8 boardobjgrpmask_bitsetcount(struct boardobjgrpmask *mask); +u8 boardobjgrpmask_bitidxlowest(struct boardobjgrpmask *mask); +u8 boardobjgrpmask_bitidxhighest(struct boardobjgrpmask *mask); + +/* Operations on a single bit of a single mask */ +u32 boardobjgrpmask_bitclr(struct boardobjgrpmask *mask, u8 bitidx); +u32 boardobjgrpmask_bitset(struct boardobjgrpmask *mask, u8 bitidx); +u32 boardobjgrpmask_bitinv(struct boardobjgrpmask *mask, u8 bitidx); +bool boardobjgrpmask_bitget(struct boardobjgrpmask *mask, u8 bitidx); + +/* Operations on a multiple masks */ +u32 boardobjgrpmask_and(struct boardobjgrpmask *dst, + struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2); +u32 boardobjgrpmask_or(struct boardobjgrpmask *dst, struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2); +u32 boardobjgrpmask_xor(struct boardobjgrpmask *dst, + struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2); + +/* Special interfaces */ +u32 boardobjgrpmask_copy(struct boardobjgrpmask *dst, + struct boardobjgrpmask *src); +bool boardobjgrpmask_sizeeq(struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2); +bool boardobjgrpmask_issubset(struct boardobjgrpmask *op1, + struct boardobjgrpmask *op2); + +/* init boardobjgrpmask_e32 structure */ +#define boardobjgrpmask_e32_init(pmaske32, pextmask) \ + boardobjgrpmask_init(&(pmaske32)->super, \ + CTRL_BOARDOBJGRP_E32_MAX_OBJECTS, (pextmask)) + +/* init boardobjgrpmask_e255 structure */ +#define boardobjgrpmask_e255_init(pmaske255, pextmask) \ + boardobjgrpmask_init(&(pmaske255)->super, \ + CTRL_BOARDOBJGRP_E255_MAX_OBJECTS, (pextmask)) + +#endif diff --git a/drivers/gpu/nvgpu/ctrl/ctrlboardobj.h b/drivers/gpu/nvgpu/ctrl/ctrlboardobj.h new file mode 100644 index 00000000..3d9599a6 --- /dev/null +++ b/drivers/gpu/nvgpu/ctrl/ctrlboardobj.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef _ctrlboardobj_h_ +#define _ctrlboardobj_h_ + +struct ctrl_boardobj { + u8 type; +}; + +#define CTRL_BOARDOBJGRP_TYPE_INVALID 0x00 +#define CTRL_BOARDOBJGRP_TYPE_E32 0x01 +#define CTRL_BOARDOBJGRP_TYPE_E255 0x02 + +#define CTRL_BOARDOBJGRP_E32_MAX_OBJECTS 32 + +#define CTRL_BOARDOBJGRP_E255_MAX_OBJECTS 255 + +#define CTRL_BOARDOBJ_MAX_BOARD_OBJECTS \ + CTRL_BOARDOBJGRP_E32_MAX_OBJECTS + +#define CTRL_BOARDOBJ_IDX_INVALID 255 + +#define CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_BIT_SIZE 32 + +#define CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_INDEX(_bit) \ + ((_bit) / CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_BIT_SIZE) + +#define CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_OFFSET(_bit) \ + ((_bit) % CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_BIT_SIZE) + +#define CTRL_BOARDOBJGRP_MASK_DATA_SIZE(_bits) \ + (CTRL_BOARDOBJGRP_MASK_MASK_ELEMENT_INDEX((_bits) - 1) + 1) + + +#define CTRL_BOARDOBJGRP_MASK_ARRAY_START_SIZE 1 +#define CTRL_BOARDOBJGRP_MASK_ARRAY_EXTENSION_SIZE(_bits) \ + (CTRL_BOARDOBJGRP_MASK_DATA_SIZE(_bits) - \ + CTRL_BOARDOBJGRP_MASK_ARRAY_START_SIZE) + +struct ctrl_boardobjgrp_mask { + u32 data[1]; +}; + +struct ctrl_boardobjgrp_mask_e32 { + struct ctrl_boardobjgrp_mask super; +}; + +struct ctrl_boardobjgrp_mask_e255 { + struct ctrl_boardobjgrp_mask super; + u32 data_e255[7]; +}; + +struct ctrl_boardobjgrp_super { + struct ctrl_boardobjgrp_mask obj_mask; +}; + +struct ctrl_boardobjgrp_e32 { + struct ctrl_boardobjgrp_mask_e32 obj_mask; +}; + +struct CTRL_boardobjgrp_e255 { + struct ctrl_boardobjgrp_mask_e255 obj_mask; +}; + +struct ctrl_boardobjgrp { + u32 obj_mask; +}; + +#endif + diff --git a/drivers/gpu/nvgpu/ctrl/ctrlclk.h b/drivers/gpu/nvgpu/ctrl/ctrlclk.h new file mode 100644 index 00000000..76054d27 --- /dev/null +++ b/drivers/gpu/nvgpu/ctrl/ctrlclk.h @@ -0,0 +1,153 @@ +/* + * general p state infrastructure + * + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#ifndef _ctrlclk_h_ +#define _ctrlclk_h_ + +#include "ctrlboardobj.h" +#include "ctrlclkavfs.h" +#include "ctrlvolt.h" + +#define CTRL_CLK_CLK_DELTA_MAX_VOLT_RAILS 4 + +/* valid clock domain values */ +#define CTRL_CLK_DOMAIN_MCLK (0x00000010) +#define CTRL_CLK_DOMAIN_DISPCLK (0x00000040) +#define CTRL_CLK_DOMAIN_GPC2CLK (0x00010000) +#define CTRL_CLK_DOMAIN_XBAR2CLK (0x00040000) +#define CTRL_CLK_DOMAIN_SYS2CLK (0x00080000) +#define CTRL_CLK_DOMAIN_HUB2CLK (0x00100000) +#define CTRL_CLK_DOMAIN_PWRCLK (0x00800000) +#define CTRL_CLK_DOMAIN_NVDCLK (0x01000000) +#define CTRL_CLK_DOMAIN_PCIEGENCLK (0x02000000) + +#define CTRL_CLK_DOMAIN_GPCCLK (0x10000000) +#define CTRL_CLK_DOMAIN_XBARCLK (0x20000000) +#define CTRL_CLK_DOMAIN_SYSCLK (0x40000000) +#define CTRL_CLK_DOMAIN_HUBCLK (0x80000000) + +#define CTRL_CLK_CLK_DOMAIN_TYPE_3X 0x01 +#define CTRL_CLK_CLK_DOMAIN_TYPE_3X_FIXED 0x02 +#define CTRL_CLK_CLK_DOMAIN_TYPE_3X_PROG 0x03 +#define CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER 0x04 +#define CTRL_CLK_CLK_DOMAIN_TYPE_3X_SLAVE 0x05 + +#define CTRL_CLK_CLK_DOMAIN_3X_PROG_ORDERING_INDEX_INVALID 0xFF +#define CTRL_CLK_CLK_DOMAIN_INDEX_INVALID 0xFF + +#define CTRL_CLK_CLK_PROG_TYPE_1X 0x00 +#define CTRL_CLK_CLK_PROG_TYPE_1X_MASTER 0x01 +#define CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_RATIO 0x02 +#define CTRL_CLK_CLK_PROG_TYPE_1X_MASTER_TABLE 0x03 +#define CTRL_CLK_CLK_PROG_TYPE_UNKNOWN 255 + +/*! + * Enumeration of CLK_PROG source types. + */ +#define CTRL_CLK_PROG_1X_SOURCE_PLL 0x00 +#define CTRL_CLK_PROG_1X_SOURCE_ONE_SOURCE 0x01 +#define CTRL_CLK_PROG_1X_SOURCE_FLL 0x02 +#define CTRL_CLK_PROG_1X_SOURCE_INVALID 255 + +#define CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES 4 +#define CTRL_CLK_PROG_1X_MASTER_MAX_SLAVE_ENTRIES 6 + +#define CTRL_CLK_CLK_VF_POINT_IDX_INVALID 255 + +#define CTRL_CLK_CLK_VF_POINT_TYPE_FREQ 0x00 +#define CTRL_CLK_CLK_VF_POINT_TYPE_VOLT 0x01 +#define CTRL_CLK_CLK_VF_POINT_TYPE_UNKNOWN 255 + +struct ctrl_clk_clk_prog_1x_master_source_fll { + u32 base_vfsmooth_volt_uv; + u32 max_vf_ramprate; + u32 max_freq_stepsize_mhz; +}; + +union ctrl_clk_clk_prog_1x_master_source_data { + struct ctrl_clk_clk_prog_1x_master_source_fll fll; +}; + +struct ctrl_clk_clk_vf_point_info_freq { + u16 freq_mhz; +}; + +struct ctrl_clk_clk_vf_point_info_volt { + u32 sourceVoltageuV; + u8 vfGainVfeEquIdx; + u8 clkDomainIdx; +}; + +struct ctrl_clk_clk_prog_1x_master_vf_entry { + u8 vfe_idx; + u8 gain_vfe_idx; + u8 vf_point_idx_first; + u8 vf_point_idx_last; +}; + +struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry { + u8 clk_dom_idx; + u8 ratio; +}; + +struct ctrl_clk_clk_prog_1x_master_table_slave_entry { + u8 clk_dom_idx; + u16 freq_mhz; +}; + +struct ctrl_clk_clk_prog_1x_source_pll { + u8 pll_idx; + u8 freq_step_size_mhz; +}; + +struct ctrl_clk_clk_delta { + int freq_delta_khz; + int volt_deltauv[CTRL_CLK_CLK_DELTA_MAX_VOLT_RAILS]; + +}; + +union ctrl_clk_clk_prog_1x_source_data { + struct ctrl_clk_clk_prog_1x_source_pll pll; +}; + +struct ctrl_clk_vf_pair { + u16 freq_mhz; + u32 voltage_uv; +}; + +struct ctrl_clk_clk_domain_list_item { + u32 clk_domain; + u32 clk_freq_khz; + u32 clk_flags; + u8 current_regime_id; + u8 target_regime_id; +}; + +#define CTRL_CLK_VF_PAIR_FREQ_MHZ_GET(pvfpair) \ + ((pvfpair)->freq_mhz) + +#define CTRL_CLK_VF_PAIR_VOLTAGE_UV_GET(pvfpair) \ + ((pvfpair)->voltage_uv) + +#define CTRL_CLK_VF_PAIR_FREQ_MHZ_SET(pvfpair, _freqmhz) \ + (((pvfpair)->freq_mhz) = (_freqmhz)) + +#define CTRL_CLK_VF_PAIR_FREQ_MHZ_SET(pvfpair, _freqmhz) \ + (((pvfpair)->freq_mhz) = (_freqmhz)) + + +#define CTRL_CLK_VF_PAIR_VOLTAGE_UV_SET(pvfpair, _voltageuv) \ + (((pvfpair)->voltage_uv) = (_voltageuv)) + +#endif diff --git a/drivers/gpu/nvgpu/ctrl/ctrlclkavfs.h b/drivers/gpu/nvgpu/ctrl/ctrlclkavfs.h new file mode 100644 index 00000000..7e28a5d9 --- /dev/null +++ b/drivers/gpu/nvgpu/ctrl/ctrlclkavfs.h @@ -0,0 +1,88 @@ +/* + * _NVRM_COPYRIGHT_BEGIN_ + * + * Copyright 2015-2016 by NVIDIA Corporation. All rights reserved. All + * information contained herein is proprietary and confidential to NVIDIA + * Corporation. Any use, reproduction, or disclosure without the written + * permission of NVIDIA Corporation is prohibited. + * + * _NVRM_COPYRIGHT_END_ + */ + +#ifndef _ctrlclkavfs_h_ +#define _ctrlclkavfs_h_ + +#include "ctrlboardobj.h" +/*! + * Valid global VIN ID values + */ +#define CTRL_CLK_VIN_ID_SYS 0x00000000 +#define CTRL_CLK_VIN_ID_LTC 0x00000001 +#define CTRL_CLK_VIN_ID_XBAR 0x00000002 +#define CTRL_CLK_VIN_ID_GPC0 0x00000003 +#define CTRL_CLK_VIN_ID_GPC1 0x00000004 +#define CTRL_CLK_VIN_ID_GPC2 0x00000005 +#define CTRL_CLK_VIN_ID_GPC3 0x00000006 +#define CTRL_CLK_VIN_ID_GPC4 0x00000007 +#define CTRL_CLK_VIN_ID_GPC5 0x00000008 +#define CTRL_CLK_VIN_ID_GPCS 0x00000009 +#define CTRL_CLK_VIN_ID_SRAM 0x0000000A +#define CTRL_CLK_VIN_ID_UNDEFINED 0x000000FF + +#define CTRL_CLK_VIN_TYPE_DISABLED 0x00000000 + +/*! + * Mask of all GPC VIN IDs supported by RM + */ +#define CTRL_CLK_VIN_MASK_UNICAST_GPC (BIT(CTRL_CLK_VIN_ID_GPC0) | \ + BIT(CTRL_CLK_VIN_ID_GPC1) | \ + BIT(CTRL_CLK_VIN_ID_GPC2) | \ + BIT(CTRL_CLK_VIN_ID_GPC3) | \ + BIT(CTRL_CLK_VIN_ID_GPC4) | \ + BIT(CTRL_CLK_VIN_ID_GPC5)) +#define CTRL_CLK_LUT_NUM_ENTRIES 0x50 +#define CTRL_CLK_VIN_STEP_SIZE_UV (10000) +#define CTRL_CLK_LUT_MIN_VOLTAGE_UV (450000) +#define CTRL_CLK_FLL_TYPE_DISABLED 0 + +#define CTRL_CLK_FLL_ID_SYS (0x00000000) +#define CTRL_CLK_FLL_ID_LTC (0x00000001) +#define CTRL_CLK_FLL_ID_XBAR (0x00000002) +#define CTRL_CLK_FLL_ID_GPC0 (0x00000003) +#define CTRL_CLK_FLL_ID_GPC1 (0x00000004) +#define CTRL_CLK_FLL_ID_GPC2 (0x00000005) +#define CTRL_CLK_FLL_ID_GPC3 (0x00000006) +#define CTRL_CLK_FLL_ID_GPC4 (0x00000007) +#define CTRL_CLK_FLL_ID_GPC5 (0x00000008) +#define CTRL_CLK_FLL_ID_GPCS (0x00000009) +#define CTRL_CLK_FLL_ID_UNDEFINED (0x000000FF) +#define CTRL_CLK_FLL_MASK_UNDEFINED (0x00000000) + +/*! + * Mask of all GPC FLL IDs supported by RM + */ +#define CTRL_CLK_FLL_MASK_UNICAST_GPC (BIT(CTRL_CLK_FLL_ID_GPC0) | \ + BIT(CTRL_CLK_FLL_ID_GPC1) | \ + BIT(CTRL_CLK_FLL_ID_GPC2) | \ + BIT(CTRL_CLK_FLL_ID_GPC3) | \ + BIT(CTRL_CLK_FLL_ID_GPC4) | \ + BIT(CTRL_CLK_FLL_ID_GPC5)) +/*! + * Mask of all FLL IDs supported by RM + */ +#define CTRL_CLK_FLL_ID_ALL_MASK (BIT(CTRL_CLK_FLL_ID_SYS) | \ + BIT(CTRL_CLK_FLL_ID_LTC) | \ + BIT(CTRL_CLK_FLL_ID_XBAR) | \ + BIT(CTRL_CLK_FLL_ID_GPC0) | \ + BIT(CTRL_CLK_FLL_ID_GPC1) | \ + BIT(CTRL_CLK_FLL_ID_GPC2) | \ + BIT(CTRL_CLK_FLL_ID_GPC3) | \ + BIT(CTRL_CLK_FLL_ID_GPC4) | \ + BIT(CTRL_CLK_FLL_ID_GPC5) | \ + BIT(CTRL_CLK_FLL_ID_GPCS)) + +#define CTRL_CLK_FLL_REGIME_ID_INVALID (0x00000000) +#define CTRL_CLK_FLL_REGIME_ID_FFR (0x00000001) +#define CTRL_CLK_FLL_REGIME_ID_FR (0x00000002) + +#endif diff --git a/drivers/gpu/nvgpu/ctrl/ctrlperf.h b/drivers/gpu/nvgpu/ctrl/ctrlperf.h new file mode 100644 index 00000000..89697dfd --- /dev/null +++ b/drivers/gpu/nvgpu/ctrl/ctrlperf.h @@ -0,0 +1,32 @@ +/* + * general p state infrastructure + * + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#ifndef _ctrlperf_h_ +#define _ctrlperf_h_ + +#include "ctrlvolt.h" + +struct ctrl_perf_volt_rail_list_item { + u8 volt_domain; + u32 voltage_uv; + u32 voltage_min_noise_unaware_uv; +}; + +struct ctrl_perf_volt_rail_list { + u8 num_rails; + struct ctrl_perf_volt_rail_list_item + rails[CTRL_VOLT_VOLT_RAIL_MAX_RAILS]; +}; + +#endif diff --git a/drivers/gpu/nvgpu/ctrl/ctrlvolt.h b/drivers/gpu/nvgpu/ctrl/ctrlvolt.h new file mode 100644 index 00000000..b4769a18 --- /dev/null +++ b/drivers/gpu/nvgpu/ctrl/ctrlvolt.h @@ -0,0 +1,40 @@ +/* + * general p state infrastructure + * + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#ifndef _ctrlvolt_h_ +#define _ctrlvolt_h_ + +#define CTRL_VOLT_VOLT_RAIL_MAX_RAILS \ + CTRL_BOARDOBJGRP_E32_MAX_OBJECTS + +#include "ctrlperf.h" +#include "ctrlboardobj.h" + +#define CTRL_VOLT_RAIL_VOLT_DELTA_MAX_ENTRIES 0x04 +#define CTRL_VOLT_VOLT_DEV_VID_VSEL_MAX_ENTRIES (8) +#define CTRL_VOLT_DOMAIN_INVALID 0x00 +#define CTRL_VOLT_DOMAIN_LOGIC 0x01 + +struct ctrl_volt_volt_rail_list_item { + u8 rail_idx; + u32 voltage_uv; +}; + +struct ctrl_volt_volt_rail_list { + u8 num_rails; + struct ctrl_volt_volt_rail_list_item + rails[CTRL_VOLT_VOLT_RAIL_MAX_RAILS]; +}; + +#endif diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index ebe2dca4..c9f84041 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -63,6 +63,9 @@ #include "hal.h" #include "vgpu/vgpu.h" #include "pci.h" +#ifdef CONFIG_ARCH_TEGRA_18x_SOC +#include "pstate/pstate.h" +#endif #define CREATE_TRACE_POINTS #include @@ -956,6 +959,16 @@ int gk20a_pm_finalize_poweron(struct device *dev) goto done; } +#ifdef CONFIG_ARCH_TEGRA_18x_SOC + if (g->ops.pmupstate) { + err = gk20a_init_pstate_support(g); + if (err) { + gk20a_err(dev, "failed to init pstates"); + goto done; + } + } +#endif + err = gk20a_init_pmu_support(g); if (err) { gk20a_err(dev, "failed to init gk20a pmu"); @@ -968,6 +981,16 @@ int gk20a_pm_finalize_poweron(struct device *dev) goto done; } +#ifdef CONFIG_ARCH_TEGRA_18x_SOC + if (g->ops.pmupstate) { + err = gk20a_init_pstate_pmu_support(g); + if (err) { + gk20a_err(dev, "failed to init pstates"); + goto done; + } + } +#endif + if (g->ops.pmu.mclk_init) { err = g->ops.pmu.mclk_init(g); if (err) { diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index c4744f3c..edc4a0e1 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -54,6 +54,11 @@ struct acr_desc; #include "debug_gk20a.h" #include "sched_gk20a.h" #include "gm206/bios_gm206.h" +#ifdef CONFIG_ARCH_TEGRA_18x_SOC +#include "clk/clk.h" +#include "perf/perf.h" +#endif +#include "gm206/bios_gm206.h" /* PTIMER_REF_FREQ_HZ corresponds to a period of 32 nanoseconds. 32 ns is the resolution of ptimer. */ @@ -607,6 +612,7 @@ struct gpu_ops { } clk; bool privsecurity; bool securegpccs; + bool pmupstate; struct { const struct regop_offset_range* ( *get_global_whitelist_ranges)(void); @@ -717,6 +723,7 @@ struct nvgpu_bios { struct bit_token *perf_token; struct bit_token *clock_token; + struct bit_token *virt_token; u32 expansion_rom_offset; }; @@ -746,6 +753,10 @@ struct gk20a { struct pmu_gk20a pmu; struct acr_desc acr; struct cooling_device_gk20a gk20a_cdev; +#ifdef CONFIG_ARCH_TEGRA_18x_SOC + struct clk_pmupstate clk_pmu; + struct perf_pmupstate perf_pmu; +#endif #ifdef CONFIG_DEBUG_FS struct railgate_stats pstats; @@ -992,6 +1003,7 @@ enum gk20a_dbg_categories { gpu_dbg_map_v = BIT(14), /* verbose mem mappings */ gpu_dbg_sema = BIT(15), /* semaphore debugging */ gpu_dbg_sema_v = BIT(16), /* verbose semaphore debugging */ + gpu_dbg_pmu_pstate = BIT(17), /* p state controlled by pmu */ gpu_dbg_mem = BIT(31), /* memory accesses, very verbose */ }; diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c index 550dffa6..b1e94d7d 100644 --- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c @@ -142,6 +142,7 @@ int gk20a_init_hal(struct gk20a *g) *gops = gk20a_ops; gops->privsecurity = 0; gops->securegpccs = 0; + gops->pmupstate = false; gk20a_init_mc(gops); gk20a_init_ltc(gops); gk20a_init_gr_ops(gops); diff --git a/drivers/gpu/nvgpu/gk20a/pmu_api.h b/drivers/gpu/nvgpu/gk20a/pmu_api.h index aa10661c..d256f6d2 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_api.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_api.h @@ -458,6 +458,29 @@ enum { PMU_PG_ELPG_CMD_UNFREEZE, }; +enum { + PMU_PG_CMD_ID_ELPG_CMD = 0, + PMU_PG_CMD_ID_ENG_BUF_LOAD, + PMU_PG_CMD_ID_ENG_BUF_UNLOAD, + PMU_PG_CMD_ID_PG_STAT, + PMU_PG_CMD_ID_PG_LOG_INIT, + PMU_PG_CMD_ID_PG_LOG_FLUSH, + PMU_PG_CMD_ID_PG_PARAM, + PMU_PG_CMD_ID_ELPG_INIT, + PMU_PG_CMD_ID_ELPG_POLL_CTXSAVE, + PMU_PG_CMD_ID_ELPG_ABORT_POLL, + PMU_PG_CMD_ID_ELPG_PWR_UP, + PMU_PG_CMD_ID_ELPG_DISALLOW, + PMU_PG_CMD_ID_ELPG_ALLOW, + PMU_PG_CMD_ID_AP, + RM_PMU_PG_CMD_ID_PSI, + RM_PMU_PG_CMD_ID_CG, + PMU_PG_CMD_ID_ZBC_TABLE_UPDATE, + PMU_PG_CMD_ID_PWR_RAIL_GATE_DISABLE = 0x20, + PMU_PG_CMD_ID_PWR_RAIL_GATE_ENABLE, + PMU_PG_CMD_ID_PWR_RAIL_SMU_MSG_DISABLE +}; + struct pmu_pg_cmd_elpg_cmd { u8 cmd_type; u8 engine_id; diff --git a/drivers/gpu/nvgpu/gk20a/pmu_common.h b/drivers/gpu/nvgpu/gk20a/pmu_common.h index 76b37cf7..de37caeb 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_common.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_common.h @@ -95,6 +95,8 @@ struct flcn_u64 { u32 hi; }; +#define nv_flcn_u64 flcn_u64 + struct flcn_mem_desc_v0 { struct flcn_u64 address; u32 params; @@ -132,6 +134,8 @@ struct pmu_allocation_v3 { } alloc; }; +#define nv_pmu_allocation pmu_allocation_v3 + struct pmu_hdr { u8 unit_id; u8 size; @@ -142,4 +146,36 @@ struct pmu_hdr { #define nv_pmu_hdr pmu_hdr typedef u8 flcn_status; -#endif /*__PMU_COMMON_H__*/ +#define ALIGN_UP(v, gran) (((v) + ((gran) - 1)) & ~((gran)-1)) + +/*! + * Falcon PMU DMA's minimum size in bytes. + */ +#define PMU_DMA_MIN_READ_SIZE_BYTES 16 +#define PMU_DMA_MIN_WRITE_SIZE_BYTES 4 + +#define PMU_FB_COPY_RW_ALIGNMENT \ + (PMU_DMA_MIN_READ_SIZE_BYTES > PMU_DMA_MIN_WRITE_SIZE_BYTES ? \ + PMU_DMA_MIN_READ_SIZE_BYTES : PMU_DMA_MIN_WRITE_SIZE_BYTES) + +/*! + * Macros to make aligned versions of RM_PMU_XXX structures. PMU needs aligned + * data structures to issue DMA read/write operations. + */ +#define NV_PMU_MAKE_ALIGNED_STRUCT(name, size) \ +union name##_aligned { \ + struct name data; \ + u8 pad[ALIGN_UP(sizeof(struct name), \ + (PMU_FB_COPY_RW_ALIGNMENT))]; \ +} + +#define NV_PMU_MAKE_ALIGNED_UNION(name, size) \ +union name##_aligned { \ + union name data; \ + u8 pad[ALIGN_UP(sizeof(union name), \ + (PMU_FB_COPY_RW_ALIGNMENT))]; \ +} + +#define NV_UNSIGNED_ROUNDED_DIV(a, b) (((a) + ((b) / 2)) / (b)) + +#endif diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index f041c9c1..13d3ec78 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -3756,9 +3756,6 @@ static int pmu_response_handle(struct pmu_gk20a *pmu, } if (pv->pmu_allocation_get_dmem_size(pmu, pv->get_pmu_seq_out_a_ptr(seq)) != 0) { - gk20a_err(dev_from_gk20a(g), "dmem offs %x size %x\n", pv->pmu_allocation_get_dmem_offset(pmu,pv->get_pmu_seq_out_a_ptr(seq)), pv->pmu_allocation_get_dmem_size(pmu, -pv->get_pmu_seq_out_a_ptr(seq))); - gk20a_err(dev_from_gk20a(g), "copying to %p \n", seq->out_payload); pmu_copy_from_dmem(pmu, pv->pmu_allocation_get_dmem_offset(pmu, pv->get_pmu_seq_out_a_ptr(seq)), diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index f0e5d3cf..fd27ab5c 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h @@ -23,6 +23,9 @@ #include "pmu_api.h" #include "pmu_common.h" +#include "pmuif/gpmuifboardobj.h" +#include "pmuif/gpmuifclk.h" +#include "pmuif/gpmuifperf.h" /* defined by pmu hw spec */ #define GK20A_PMU_VA_SIZE (512 * 1024 * 1024) @@ -172,8 +175,10 @@ struct pmu_ucode_desc_v1 { #define PMU_UNIT_ACR (0x0A) #define PMU_UNIT_PERFMON_T18X (0x11) #define PMU_UNIT_PERFMON (0x12) -#define PMU_UNIT_RC (0x1F) +#define PMU_UNIT_PERF (0x13) +#define PMU_UNIT_RC (0x1F) #define PMU_UNIT_FECS_MEM_OVERRIDE (0x1E) +#define PMU_UNIT_CLK (0x1C) #define PMU_UNIT_END (0x23) @@ -295,29 +300,6 @@ struct pmu_rc_msg { struct pmu_rc_msg_unhandled_cmd unhandled_cmd; }; -enum { - PMU_PG_CMD_ID_ELPG_CMD = 0, - PMU_PG_CMD_ID_ENG_BUF_LOAD, - PMU_PG_CMD_ID_ENG_BUF_UNLOAD, - PMU_PG_CMD_ID_PG_STAT, - PMU_PG_CMD_ID_PG_LOG_INIT, - PMU_PG_CMD_ID_PG_LOG_FLUSH, - PMU_PG_CMD_ID_PG_PARAM, - PMU_PG_CMD_ID_ELPG_INIT, - PMU_PG_CMD_ID_ELPG_POLL_CTXSAVE, - PMU_PG_CMD_ID_ELPG_ABORT_POLL, - PMU_PG_CMD_ID_ELPG_PWR_UP, - PMU_PG_CMD_ID_ELPG_DISALLOW, - PMU_PG_CMD_ID_ELPG_ALLOW, - PMU_PG_CMD_ID_AP, - RM_PMU_PG_CMD_ID_PSI, - RM_PMU_PG_CMD_ID_CG, - PMU_PG_CMD_ID_ZBC_TABLE_UPDATE, - PMU_PG_CMD_ID_PWR_RAIL_GATE_DISABLE = 0x20, - PMU_PG_CMD_ID_PWR_RAIL_GATE_ENABLE, - PMU_PG_CMD_ID_PWR_RAIL_SMU_MSG_DISABLE -}; - /***************************** ACR ERROR CODES ******************************/ /*! * Error codes used in PMU-ACR Task @@ -369,6 +351,9 @@ struct pmu_cmd { struct pmu_zbc_cmd zbc; struct pmu_acr_cmd acr; struct pmu_lrf_tex_ltc_dram_cmd lrf_tex_ltc_dram; + struct nv_pmu_boardobj_cmd boardobj; + struct nv_pmu_perf_cmd perf; + struct nv_pmu_clk_cmd clk; } cmd; }; @@ -381,6 +366,9 @@ struct pmu_msg { struct pmu_rc_msg rc; struct pmu_acr_msg acr; struct pmu_lrf_tex_ltc_dram_msg lrf_tex_ltc_dram; + struct nv_pmu_boardobj_msg boardobj; + struct nv_pmu_perf_msg perf; + struct nv_pmu_clk_msg clk; } msg; }; @@ -813,4 +801,6 @@ int gk20a_pmu_vidmem_surface_alloc(struct gk20a *g, struct mem_desc *mem, u32 size); int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct mem_desc *mem, u32 size); + +void print_vbios_table(u8 *msg, u8 *buff, int size); #endif /*__PMU_GK20A_H__*/ diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.c b/drivers/gpu/nvgpu/gm206/bios_gm206.c index 6caecb32..21c852a5 100644 --- a/drivers/gpu/nvgpu/gm206/bios_gm206.c +++ b/drivers/gpu/nvgpu/gm206/bios_gm206.c @@ -61,6 +61,7 @@ struct bit { #define TOKEN_ID_FALCON_DATA 0x70 #define TOKEN_ID_PERF_PTRS 0x50 #define TOKEN_ID_CLOCK_PTRS 0x43 +#define TOKEN_ID_VIRT_PTRS 0x56 struct nvinit_ptrs { u16 initscript_table_ptr; @@ -434,17 +435,29 @@ static void *gm206_bios_get_perf_table_ptrs(struct gk20a *g, { u32 perf_table_id_offset = 0; u8 *perf_table_ptr = NULL; + u8 data_size = 4; - if (ptoken != NULL && - table_id < (ptoken->data_size/sizeof(u32))) { + if (ptoken != NULL) { - perf_table_id_offset = *((u32 *)&g->bios.data[ + if (ptoken->token_id == TOKEN_ID_VIRT_PTRS) { + perf_table_id_offset = *((u16 *)&g->bios.data[ + ptoken->data_ptr + + (table_id * PERF_PTRS_WIDTH_16)]); + data_size = PERF_PTRS_WIDTH_16; + } else { + perf_table_id_offset = *((u32 *)&g->bios.data[ ptoken->data_ptr + (table_id * PERF_PTRS_WIDTH)]); + data_size = PERF_PTRS_WIDTH; + } + } else + return (void *)perf_table_ptr; + + if (table_id < (ptoken->data_size/data_size)) { gk20a_dbg_info("Perf_Tbl_ID-offset 0x%x Tbl_ID_Ptr-offset- 0x%x", (ptoken->data_ptr + - (table_id * PERF_PTRS_WIDTH)), + (table_id * data_size)), perf_table_id_offset); if (perf_table_id_offset != 0) { @@ -503,6 +516,10 @@ static void gm206_bios_parse_bit(struct gk20a *g, int offset) g->bios.clock_token = (struct bit_token *)&g->bios.data[offset]; break; + case TOKEN_ID_VIRT_PTRS: + g->bios.virt_token = + (struct bit_token *)&g->bios.data[offset]; + break; default: break; } diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.h b/drivers/gpu/nvgpu/gm206/bios_gm206.h index f93e5f58..5aa20364 100644 --- a/drivers/gpu/nvgpu/gm206/bios_gm206.h +++ b/drivers/gpu/nvgpu/gm206/bios_gm206.h @@ -15,18 +15,34 @@ #define NVGPU_BIOS_GM206_H #define PERF_PTRS_WIDTH 0x4 +#define PERF_PTRS_WIDTH_16 0x2 enum { CLOCKS_TABLE = 2, CLOCK_PROGRAMMING_TABLE, - NAFLL_TABLE, - ADC_TABLE, + FLL_TABLE, + VIN_TABLE, + FREQUENCY_CONTROLLER_TABLE }; enum { + PERFORMANCE_TABLE = 0, + MEMORY_CLOCK_TABLE, + MEMORY_TWEAK_TABLE, + POWER_CONTROL_TABLE, + THERMAL_CONTROL_TABLE, + THERMAL_DEVICE_TABLE, + THERMAL_COOLERS_TABLE, + PERFORMANCE_SETTINGS_SCRIPT, CONTINUOUS_VIRTUAL_BINNING_TABLE, }; +enum { + VP_FIELD_TABLE = 0, + VP_FIELD_REGISTER, + VP_TRANSLATION_TABLE, +}; + struct bit_token { u8 token_id; u8 data_version; diff --git a/drivers/gpu/nvgpu/gm206/hal_gm206.c b/drivers/gpu/nvgpu/gm206/hal_gm206.c index 6b43c8e9..f771c07d 100644 --- a/drivers/gpu/nvgpu/gm206/hal_gm206.c +++ b/drivers/gpu/nvgpu/gm206/hal_gm206.c @@ -181,7 +181,7 @@ int gm206_init_hal(struct gk20a *g) gops->privsecurity = 1; gops->securegpccs = 1; - + gops->pmupstate = false; gm20b_init_mc(gops); gm20b_init_ltc(gops); gm206_init_gr(gops); diff --git a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c index 5133fb35..1c601894 100644 --- a/drivers/gpu/nvgpu/gm20b/hal_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/hal_gm20b.c @@ -184,6 +184,7 @@ int gm20b_init_hal(struct gk20a *g) *gops = gm20b_ops; gops->securegpccs = false; + gops->pmupstate = false; #ifdef CONFIG_TEGRA_ACR if (platform->is_fmodel) { gops->privsecurity = 1; diff --git a/drivers/gpu/nvgpu/pmuif/gpmuifbios.h b/drivers/gpu/nvgpu/pmuif/gpmuifbios.h new file mode 100644 index 00000000..2581d3fa --- /dev/null +++ b/drivers/gpu/nvgpu/pmuif/gpmuifbios.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#ifndef _GPMUIFBIOS_H_ +#define _GPMUIFBIOS_H_ + +struct nv_pmu_bios_vfield_register_segment_super { + u8 type; + u8 low_bit; + u8 high_bit; +}; + +struct nv_pmu_bios_vfield_register_segment_reg { + struct nv_pmu_bios_vfield_register_segment_super super; + u32 addr; +}; + +struct nv_pmu_bios_vfield_register_segment_index_reg { + struct nv_pmu_bios_vfield_register_segment_super super; + u32 addr; + u32 reg_index; + u32 index; +}; + +union nv_pmu_bios_vfield_register_segment { + struct nv_pmu_bios_vfield_register_segment_super super; + struct nv_pmu_bios_vfield_register_segment_reg reg; + struct nv_pmu_bios_vfield_register_segment_index_reg index_reg; +}; + + +#endif /* _GPMUIFBIOS_H_*/ diff --git a/drivers/gpu/nvgpu/pmuif/gpmuifboardobj.h b/drivers/gpu/nvgpu/pmuif/gpmuifboardobj.h new file mode 100644 index 00000000..7a061472 --- /dev/null +++ b/drivers/gpu/nvgpu/pmuif/gpmuifboardobj.h @@ -0,0 +1,196 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ +#ifndef _GPMUIFBOARDOBJ_H_ +#define _GPMUIFBOARDOBJ_H_ + +#include "gk20a/gk20a.h" +#include "gk20a/pmu_gk20a.h" +#include "ctrl/ctrlboardobj.h" + +/* + * Base structure describing a BOARDOBJ for communication between Kernel and + * PMU. + */ +struct nv_pmu_boardobj { + u8 type; +}; + +/* + * Base structure describing a BOARDOBJ for Query interface between Kernel and + * PMU. + */ +struct nv_pmu_boardobj_query { + u8 type; +}; + +/* + * Virtual base structure describing a BOARDOBJGRP interface between Kernel and + * PMU. + */ +struct nv_pmu_boardobjgrp_super { + u8 type; + u8 class_id; + u8 obj_slots; + u8 rsvd; +}; + +struct nv_pmu_boardobjgrp { + struct nv_pmu_boardobjgrp_super super; + u32 obj_mask; +}; + +struct nv_pmu_boardobjgrp_e32 { + struct nv_pmu_boardobjgrp_super super; + struct ctrl_boardobjgrp_mask_e32 obj_mask; +}; + +struct nv_pmu_boardobjgrp_e255 { + struct nv_pmu_boardobjgrp_super super; + struct ctrl_boardobjgrp_mask_e255 obj_mask; +}; + +struct nv_pmu_boardobj_cmd_grp_payload { + struct pmu_allocation_v3 dmem_buf; + struct flcn_mem_desc_v0 fb; + u8 hdr_size; + u8 entry_size; +}; + +struct nv_pmu_boardobj_cmd_grp { + u8 cmd_type; + u8 pad[2]; + u8 class_id; + struct nv_pmu_boardobj_cmd_grp_payload grp; +}; + +#define NV_PMU_BOARDOBJ_GRP_ALLOC_OFFSET \ + (NV_OFFSETOF(NV_PMU_BOARDOBJ_CMD_GRP, grp)) + +struct nv_pmu_boardobj_cmd { + union { + u8 cmd_type; + struct nv_pmu_boardobj_cmd_grp grp; + struct nv_pmu_boardobj_cmd_grp grp_set; + struct nv_pmu_boardobj_cmd_grp grp_get_status; + }; +}; + +struct nv_pmu_boardobj_msg_grp { + u8 msg_type; + bool b_success; + flcn_status flcn_status; + u8 class_id; +}; + +struct nv_pmu_boardobj_msg { + union { + u8 msg_type; + struct nv_pmu_boardobj_msg_grp grp; + struct nv_pmu_boardobj_msg_grp grp_set; + struct nv_pmu_boardobj_msg_grp grp_get_status; + }; +}; + +/* +* Macro generating structures describing classes which implement +* NV_PMU_BOARDOBJGRP via the NV_PMU_BOARDBOBJ_CMD_GRP SET interface. +* +* @para _eng Name of implementing engine in which this structure is +* found. +* @param _class Class ID of Objects within Board Object Group. +* @param _slots Max number of elements this group can contain. +*/ +#define NV_PMU_BOARDOBJ_GRP_SET_MAKE(_eng, _class, _slots) \ + NV_PMU_MAKE_ALIGNED_STRUCT( \ + nv_pmu_##_eng##_##_class##_boardobjgrp_set_header, one_structure); \ + NV_PMU_MAKE_ALIGNED_UNION( \ + nv_pmu_##_eng##_##_class##_boardobj_set_union, one_union); \ + struct nv_pmu_##_eng##_##_class##_boardobj_grp_set { \ + union nv_pmu_##_eng##_##_class##_boardobjgrp_set_header_aligned hdr; \ + union nv_pmu_##_eng##_##_class##_boardobj_set_union_aligned objects[(_slots)];\ + } + +/* +* Macro generating structures describing classes which implement +* NV_PMU_BOARDOBJGRP_E32 via the NV_PMU_BOARDBOBJ_CMD_GRP SET interface. +* +* @para _eng Name of implementing engine in which this structure is +* found. +* @param _class Class ID of Objects within Board Object Group. +*/ +#define NV_PMU_BOARDOBJ_GRP_SET_MAKE_E32(_eng, _class) \ + NV_PMU_BOARDOBJ_GRP_SET_MAKE(_eng, _class, \ + CTRL_BOARDOBJGRP_E32_MAX_OBJECTS) + +/* +* Macro generating structures describing classes which implement +* NV_PMU_BOARDOBJGRP_E255 via the NV_PMU_BOARDBOBJ_CMD_GRP SET interface. +* +* @para _eng Name of implementing engine in which this structure is +* found. +* @param _class Class ID of Objects within Board Object Group. +*/ +#define NV_PMU_BOARDOBJ_GRP_SET_MAKE_E255(_eng, _class) \ + NV_PMU_BOARDOBJ_GRP_SET_MAKE(_eng, _class, \ + CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) + +/* +* Macro generating structures for querying dynamic state for classes which +* implement NV_PMU_BOARDOBJGRP via the NV_PMU_BOARDOBJ_CMD_GRP GET_STATUS +* interface. +* +* @para _eng Name of implementing engine in which this structure is +* found. +* @param _class Class ID of Objects within Board Object Group. +* @param _slots Max number of elements this group can contain. +*/ +#define NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE(_eng, _class, _slots) \ + NV_PMU_MAKE_ALIGNED_STRUCT( \ + nv_pmu_##_eng##_##_class##_boardobjgrp_get_status_header, struct); \ + NV_PMU_MAKE_ALIGNED_UNION( \ + nv_pmu_##_eng##_##_class##_boardobj_get_status_union, union); \ + struct nv_pmu_##_eng##_##_class##_boardobj_grp_get_status { \ + union nv_pmu_##_eng##_##_class##_boardobjgrp_get_status_header_aligned \ + hdr; \ + union nv_pmu_##_eng##_##_class##_boardobj_get_status_union_aligned \ + objects[(_slots)]; \ + } + +/* +* Macro generating structures for querying dynamic state for classes which +* implement NV_PMU_BOARDOBJGRP_E32 via the NV_PMU_BOARDOBJ_CMD_GRP GET_STATUS +* interface. +* +* @para _eng Name of implementing engine in which this structure is +* found. +* @param _class Class ID of Objects within Board Object Group. +*/ +#define NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE_E32(_eng, _class) \ + NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE(_eng, _class, \ + CTRL_BOARDOBJGRP_E32_MAX_OBJECTS) + +/* +* Macro generating structures for querying dynamic state for classes which +* implement NV_PMU_BOARDOBJGRP_E255 via the NV_PMU_BOARDOBJ_CMD_GRP GET_STATUS +* interface. +* +* @para _eng Name of implementing engine in which this structure is +* found. +* @param _class Class ID of Objects within Board Object Group. +*/ +#define NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE_E255(_eng, _class) \ + NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE(_eng, _class, \ + CTRL_BOARDOBJGRP_E255_MAX_OBJECTS) + + +#endif /* _GPMUIFBOARDOBJ_H_ */ diff --git a/drivers/gpu/nvgpu/pmuif/gpmuifclk.h b/drivers/gpu/nvgpu/pmuif/gpmuifclk.h new file mode 100644 index 00000000..36b9aace --- /dev/null +++ b/drivers/gpu/nvgpu/pmuif/gpmuifclk.h @@ -0,0 +1,414 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ + +#ifndef _GPMUIFCLK_H_ +#define _GPMUIFCLK_H_ + +#include "gk20a/gk20a.h" +#include "gk20a/pmu_gk20a.h" +#include "ctrl/ctrlboardobj.h" +#include "ctrl/ctrlvolt.h" +#include "ctrl/ctrlperf.h" +#include "ctrl/ctrlclk.h" +#include "pmuif/gpmuifboardobj.h" +#include "pmuif/gpmuifvolt.h" +#include "gk20a/pmu_common.h" + +enum nv_pmu_clk_clkwhich { + clkwhich_mclk = 5, + clkwhich_dispclk = 7, + clkwhich_gpc2clk = 17, + clkwhich_xbar2clk = 19, + clkwhich_sys2clk = 20, + clkwhich_hub2clk = 21, + clkwhich_pwrclk = 24, + clkwhich_nvdclk = 25, + clkwhich_pciegenclk = 31, +}; + +/* + * Enumeration of BOARDOBJGRP class IDs within OBJCLK. Used as "classId" + * argument for communications between Kernel and PMU via the various generic + * BOARDOBJGRP interfaces. + */ +#define NV_PMU_CLK_BOARDOBJGRP_CLASS_ID_CLK_DOMAIN 0x00 +#define NV_PMU_CLK_BOARDOBJGRP_CLASS_ID_CLK_PROG 0x01 +#define NV_PMU_CLK_BOARDOBJGRP_CLASS_ID_VIN_DEVICE 0x02 +#define NV_PMU_CLK_BOARDOBJGRP_CLASS_ID_FLL_DEVICE 0x03 +#define NV_PMU_CLK_BOARDOBJGRP_CLASS_ID_CLK_VF_POINT 0x04 + +/*! +* CLK_DOMAIN BOARDOBJGRP Header structure. Describes global state about the +* CLK_DOMAIN feature. +*/ +struct nv_pmu_clk_clk_domain_boardobjgrp_set_header { + struct nv_pmu_boardobjgrp_e32 super; + u32 vbios_domains; + struct ctrl_boardobjgrp_mask_e32 master_domains_mask; + u16 cntr_sampling_periodms; + bool b_override_o_v_o_c; + bool b_debug_mode; + bool b_enforce_vf_monotonicity; + u8 volt_rails_max; + struct ctrl_clk_clk_delta deltas; +}; + +struct nv_pmu_clk_clk_domain_boardobj_set { + struct nv_pmu_boardobj super; + enum nv_pmu_clk_clkwhich domain; + u32 api_domain; + u8 perf_domain_grp_idx; +}; + +struct nv_pmu_clk_clk_domain_3x_boardobj_set { + struct nv_pmu_clk_clk_domain_boardobj_set super; + bool b_noise_aware_capable; +}; + +struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set { + struct nv_pmu_clk_clk_domain_3x_boardobj_set super; + u16 freq_mhz; +}; + +struct nv_pmu_clk_clk_domain_3x_prog_boardobj_set { + struct nv_pmu_clk_clk_domain_3x_boardobj_set super; + u8 clk_prog_idx_first; + u8 clk_prog_idx_last; + u8 noise_unaware_ordering_index; + u8 noise_aware_ordering_index; + bool b_force_noise_unaware_ordering; + int factory_offset_khz; + short freq_delta_min_mhz; + short freq_delta_max_mhz; + struct ctrl_clk_clk_delta deltas; +}; + +struct nv_pmu_clk_clk_domain_3x_master_boardobj_set { + struct nv_pmu_clk_clk_domain_3x_prog_boardobj_set super; + u32 slave_idxs_mask; +}; + +struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set { + struct nv_pmu_clk_clk_domain_3x_prog_boardobj_set super; + u8 master_idx; +}; + +union nv_pmu_clk_clk_domain_boardobj_set_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_clk_clk_domain_boardobj_set super; + struct nv_pmu_clk_clk_domain_3x_boardobj_set v3x; + struct nv_pmu_clk_clk_domain_3x_fixed_boardobj_set v3x_fixed; + struct nv_pmu_clk_clk_domain_3x_prog_boardobj_set v3x_prog; + struct nv_pmu_clk_clk_domain_3x_master_boardobj_set v3x_master; + struct nv_pmu_clk_clk_domain_3x_slave_boardobj_set v3x_slave; +}; + +NV_PMU_BOARDOBJ_GRP_SET_MAKE_E32(clk, clk_domain); + +struct nv_pmu_clk_clk_prog_boardobjgrp_set_header { + struct nv_pmu_boardobjgrp_e255 super; + u8 slave_entry_count; + u8 vf_entry_count; +}; + +struct nv_pmu_clk_clk_prog_boardobj_set { + struct nv_pmu_boardobj super; +}; + +struct nv_pmu_clk_clk_prog_1x_boardobj_set { + struct nv_pmu_clk_clk_prog_boardobj_set super; + u8 source; + u16 freq_max_mhz; + union ctrl_clk_clk_prog_1x_source_data source_data; +}; + +struct nv_pmu_clk_clk_prog_1x_master_boardobj_set { + struct nv_pmu_clk_clk_prog_1x_boardobj_set super; + bool b_o_c_o_v_enabled; + struct ctrl_clk_clk_prog_1x_master_vf_entry vf_entries[ + CTRL_CLK_CLK_PROG_1X_MASTER_VF_ENTRY_MAX_ENTRIES]; + struct ctrl_clk_clk_delta deltas; +}; + +struct nv_pmu_clk_clk_prog_1x_master_ratio_boardobj_set { + struct nv_pmu_clk_clk_prog_1x_master_boardobj_set super; + struct ctrl_clk_clk_prog_1x_master_ratio_slave_entry slave_entries[ + CTRL_CLK_PROG_1X_MASTER_MAX_SLAVE_ENTRIES]; +}; + +struct nv_pmu_clk_clk_prog_1x_master_table_boardobj_set { + struct nv_pmu_clk_clk_prog_1x_master_boardobj_set super; + struct ctrl_clk_clk_prog_1x_master_table_slave_entry + slave_entries[CTRL_CLK_PROG_1X_MASTER_MAX_SLAVE_ENTRIES]; +}; + +union nv_pmu_clk_clk_prog_boardobj_set_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_clk_clk_prog_boardobj_set super; + struct nv_pmu_clk_clk_prog_1x_boardobj_set v1x; + struct nv_pmu_clk_clk_prog_1x_master_boardobj_set v1x_master; + struct nv_pmu_clk_clk_prog_1x_master_ratio_boardobj_set v1x_master_ratio; + struct nv_pmu_clk_clk_prog_1x_master_table_boardobj_set v1x_master_table; +}; + +NV_PMU_BOARDOBJ_GRP_SET_MAKE_E255(clk, clk_prog); + +struct nv_pmu_clk_lut_device_desc { + u8 vselect_mode; + u16 hysteresis_threshold; +}; + +struct nv_pmu_clk_regime_desc { + u8 regime_id; + u16 fixed_freq_regime_limit_mhz; +}; + +struct nv_pmu_clk_clk_fll_device_boardobjgrp_set_header { + struct nv_pmu_boardobjgrp_e32 super; + struct ctrl_boardobjgrp_mask_e32 lut_prog_master_mask; + u32 lut_step_size_uv; + u32 lut_min_voltage_uv; + u8 lut_num_entries; + u16 max_min_freq_mhz; +}; + +struct nv_pmu_clk_clk_fll_device_boardobj_set { + struct nv_pmu_boardobj super; + u8 id; + u8 mdiv; + u8 vin_idx_logic; + u8 vin_idx_sram; + u8 rail_idx_for_lut; + u16 input_freq_mhz; + u32 clk_domain; + struct nv_pmu_clk_lut_device_desc lut_device; + struct nv_pmu_clk_regime_desc regime_desc; + u8 min_freq_vfe_idx; + u8 freq_ctrl_idx; + struct ctrl_boardobjgrp_mask_e32 lut_prog_broadcast_slave_mask; +}; + +union nv_pmu_clk_clk_fll_device_boardobj_set_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_clk_clk_fll_device_boardobj_set super; +}; + +NV_PMU_BOARDOBJ_GRP_SET_MAKE_E32(clk, clk_fll_device); + +struct nv_pmu_clk_clk_vin_device_boardobjgrp_set_header { + struct nv_pmu_boardobjgrp_e32 super; + bool b_vin_is_disable_allowed; +}; + +struct nv_pmu_clk_clk_vin_device_boardobj_set { + struct nv_pmu_boardobj super; + u8 id; + u8 volt_domain; + u32 slope; + u32 intercept; + u32 flls_shared_mask; +}; + +union nv_pmu_clk_clk_vin_device_boardobj_set_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_clk_clk_vin_device_boardobj_set super; +}; + +NV_PMU_BOARDOBJ_GRP_SET_MAKE_E32(clk, clk_vin_device); + +struct nv_pmu_clk_clk_vf_point_boardobjgrp_set_header { + struct nv_pmu_boardobjgrp_e255 super; +}; + +struct nv_pmu_clk_clk_vf_point_boardobj_set { + struct nv_pmu_boardobj super; + u8 vfe_equ_idx; + u8 volt_rail_idx; +}; + +struct nv_pmu_clk_clk_vf_point_freq_boardobj_set { + struct nv_pmu_clk_clk_vf_point_boardobj_set super; + u16 freq_mhz; + int volt_delta_uv; +}; + +struct nv_pmu_clk_clk_vf_point_volt_boardobj_set { + struct nv_pmu_clk_clk_vf_point_boardobj_set super; + u32 source_voltage_uv; + u8 vf_gain_vfe_equ_idx; + u8 clk_domain_idx; + int freq_delta_khz; +}; + +union nv_pmu_clk_clk_vf_point_boardobj_set_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_clk_clk_vf_point_boardobj_set super; + struct nv_pmu_clk_clk_vf_point_freq_boardobj_set freq; + struct nv_pmu_clk_clk_vf_point_volt_boardobj_set volt; +}; + +NV_PMU_BOARDOBJ_GRP_SET_MAKE_E255(clk, clk_vf_point); + +struct nv_pmu_clk_clk_vf_point_boardobjgrp_get_status_header { + struct nv_pmu_boardobjgrp_e255 super; +}; + +struct nv_pmu_clk_clk_vf_point_boardobj_get_status { + struct nv_pmu_boardobj super; + struct ctrl_clk_vf_pair pair; +}; + +struct nv_pmu_clk_clk_vf_point_volt_boardobj_get_status { + struct nv_pmu_clk_clk_vf_point_boardobj_get_status super; + u16 vf_gain_value; +}; + +union nv_pmu_clk_clk_vf_point_boardobj_get_status_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_clk_clk_vf_point_boardobj_get_status super; + struct nv_pmu_clk_clk_vf_point_volt_boardobj_get_status volt; +}; + +NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE_E255(clk, clk_vf_point); + +#define NV_PMU_VF_INJECT_MAX_CLOCK_DOMAINS (12) + +struct nv_pmu_clk_clk_domain_list { + u8 num_domains; + struct ctrl_clk_clk_domain_list_item clk_domains[ + NV_PMU_VF_INJECT_MAX_CLOCK_DOMAINS]; +}; + +struct nv_pmu_clk_vf_change_inject { + u8 flags; + struct nv_pmu_clk_clk_domain_list clk_list; + struct nv_pmu_volt_volt_rail_list volt_list; +}; + +#define NV_NV_PMU_CLK_LOAD_FEATURE_VIN (0x00000002) +#define NV_NV_PMU_CLK_LOAD_ACTION_MASK_VIN_HW_CAL_PROGRAM_YES (0x00000001) + +struct nv_pmu_clk_load_payload_freq_controllers { + struct ctrl_boardobjgrp_mask_e32 load_mask; +}; + +struct nv_pmu_clk_load { + u8 feature; + u32 action_mask; + union { + struct nv_pmu_clk_load_payload_freq_controllers freq_controllers; + } payload; +}; + +/* CLK CMD ID definitions. */ +#define NV_PMU_CLK_CMD_ID_BOARDOBJ_GRP_SET (0x00000000) +#define NV_PMU_CLK_CMD_ID_RPC (0x00000001) +#define NV_PMU_CLK_CMD_ID_BOARDOBJ_GRP_GET_STATUS (0x00000002) + +#define NV_PMU_CLK_RPC_ID_LOAD (0x00000002) +#define NV_PMU_CLK_RPC_ID_CLK_VF_CHANGE_INJECT (0x00000001) + +struct nv_pmu_clk_cmd_rpc { + u8 cmd_type; + u8 pad[3]; + struct nv_pmu_allocation request; +}; + +#define NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET \ + (offsetof(struct nv_pmu_clk_cmd_rpc, request)) + +struct nv_pmu_clk_cmd { + union { + u8 cmd_type; + struct nv_pmu_boardobj_cmd_grp grp_set; + struct nv_pmu_clk_cmd_rpc rpc; + struct nv_pmu_boardobj_cmd_grp grp_get_status; + }; +}; + +struct nv_pmu_clk_rpc { + u8 function; + bool b_supported; + bool b_success; + flcn_status flcn_status; + union { + struct nv_pmu_clk_vf_change_inject clk_vf_change_inject; + struct nv_pmu_clk_load clk_load; + } params; +}; + +/* CLK MSG ID definitions */ +#define NV_PMU_CLK_MSG_ID_BOARDOBJ_GRP_SET (0x00000000) +#define NV_PMU_CLK_MSG_ID_RPC (0x00000001) +#define NV_PMU_CLK_MSG_ID_BOARDOBJ_GRP_GET_STATUS (0x00000002) + +struct nv_pmu_clk_msg_rpc { + u8 msg_type; + u8 rsvd[3]; + struct nv_pmu_allocation response; +}; + +#define NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET \ + offsetof(struct nv_pmu_clk_msg_rpc, response) + +struct nv_pmu_clk_msg { + union { + u8 msg_type; + struct nv_pmu_boardobj_msg_grp grp_set; + struct nv_pmu_clk_msg_rpc rpc; + struct nv_pmu_boardobj_msg_grp grp_get_status; + }; +}; + +struct nv_pmu_clk_clk_vin_device_boardobjgrp_get_status_header { + struct nv_pmu_boardobjgrp_e32 super; +}; + +struct nv_pmu_clk_clk_vin_device_boardobj_get_status { + struct nv_pmu_boardobj_query super; + u32 actual_voltage_uv; + u32 corrected_voltage_uv; + u8 sampled_code; + u8 override_code; +}; + +union nv_pmu_clk_clk_vin_device_boardobj_get_status_union { + struct nv_pmu_boardobj_query board_obj; + struct nv_pmu_clk_clk_vin_device_boardobj_get_status super; +}; + +NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE_E32(clk, clk_vin_device); + +struct nv_pmu_clk_lut_vf_entry { + u32 entry; +}; + +struct nv_pmu_clk_clk_fll_device_boardobjgrp_get_status_header { + struct nv_pmu_boardobjgrp_e32 super; +}; + +struct nv_pmu_clk_clk_fll_device_boardobj_get_status { + struct nv_pmu_boardobj_query super; + u8 current_regime_id; + u16 min_freq_mhz; + struct nv_pmu_clk_lut_vf_entry lut_vf_curve[NV_UNSIGNED_ROUNDED_DIV(CTRL_CLK_LUT_NUM_ENTRIES, 2)]; +}; + +union nv_pmu_clk_clk_fll_device_boardobj_get_status_union { + struct nv_pmu_boardobj_query board_obj; + struct nv_pmu_clk_clk_fll_device_boardobj_get_status super; +}; + +NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE_E32(clk, clk_fll_device); + +#endif /*_GPMUIFCLK_H_*/ diff --git a/drivers/gpu/nvgpu/pmuif/gpmuifperf.h b/drivers/gpu/nvgpu/pmuif/gpmuifperf.h new file mode 100644 index 00000000..b1d2f3fd --- /dev/null +++ b/drivers/gpu/nvgpu/pmuif/gpmuifperf.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#ifndef _GPMUIFPERF_H_ +#define _GPMUIFPERF_H_ + +#include "gpmuifvolt.h" +#include "gpmuifperfvfe.h" + +/* +* Enumeration of BOARDOBJGRP class IDs within OBJPERF. Used as "classId" +* argument for communications between Kernel and PMU via the various generic +* BOARDOBJGRP interfaces. +*/ +#define NV_PMU_PERF_BOARDOBJGRP_CLASS_ID_VFE_VAR 0x00 +#define NV_PMU_PERF_BOARDOBJGRP_CLASS_ID_VFE_EQU 0x01 + +#define NV_PMU_PERF_CMD_ID_RPC (0x00000002) +#define NV_PMU_PERF_CMD_ID_BOARDOBJ_GRP_SET (0x00000003) +#define NV_PMU_PERF_CMD_ID_BOARDOBJ_GRP_GET_STATUS (0x00000004) + +struct nv_pmu_perf_cmd_set_object { + u8 cmd_type; + u8 pad[2]; + u8 object_type; + struct nv_pmu_allocation object; +}; + +#define NV_PMU_PERF_SET_OBJECT_ALLOC_OFFSET \ + (offsetof(struct nv_pmu_perf_cmd_set_object, object)) + +/* RPC IDs */ +#define NV_PMU_PERF_RPC_ID_VFE_LOAD (0x00000001) + +/*! +* Command requesting execution of the perf RPC. +*/ +struct nv_pmu_perf_cmd_rpc { + u8 cmd_type; + u8 pad[3]; + struct nv_pmu_allocation request; +}; + +#define NV_PMU_PERF_CMD_RPC_ALLOC_OFFSET \ + offsetof(struct nv_pmu_perf_cmd_rpc, request) + +/*! +* Simply a union of all specific PERF commands. Forms the general packet +* exchanged between the Kernel and PMU when sending and receiving PERF commands +* (respectively). +*/ +struct nv_pmu_perf_cmd { + union { + u8 cmd_type; + struct nv_pmu_perf_cmd_set_object set_object; + struct nv_pmu_boardobj_cmd_grp grp_set; + struct nv_pmu_boardobj_cmd_grp grp_get_status; + }; +}; + +/*! +* Defines the data structure used to invoke PMU perf RPCs. Same structure is +* used to return the result of the RPC execution. +*/ +struct nv_pmu_perf_rpc { + u8 function; + bool b_supported; + bool b_success; + flcn_status flcn_status; + union { + struct nv_pmu_perf_rpc_vfe_equ_eval vfe_equ_eval; + struct nv_pmu_perf_rpc_vfe_load vfe_load; + } params; +}; + + +/* PERF Message-type Definitions */ +#define NV_PMU_PERF_MSG_ID_RPC (0x00000003) +#define NV_PMU_PERF_MSG_ID_BOARDOBJ_GRP_SET (0x00000004) +#define NV_PMU_PERF_MSG_ID_BOARDOBJ_GRP_GET_STATUS (0x00000006) + +/*! +* Message carrying the result of the perf RPC execution. +*/ +struct nv_pmu_perf_msg_rpc { + u8 msg_type; + u8 rsvd[3]; + struct nv_pmu_allocation response; +}; + +#define NV_PMU_PERF_MSG_RPC_ALLOC_OFFSET \ + (offsetof(struct nv_pmu_perf_msg_rpc, response)) + +/*! +* Simply a union of all specific PERF messages. Forms the general packet +* exchanged between the Kernel and PMU when sending and receiving PERF messages +* (respectively). +*/ +struct nv_pmu_perf_msg { + union { + u8 msg_type; + struct nv_pmu_perf_msg_rpc rpc; + struct nv_pmu_boardobj_msg_grp grp_set; + }; +}; + +#endif /* _GPMUIFPERF_H_*/ diff --git a/drivers/gpu/nvgpu/pmuif/gpmuifperfvfe.h b/drivers/gpu/nvgpu/pmuif/gpmuifperfvfe.h new file mode 100644 index 00000000..6bad6445 --- /dev/null +++ b/drivers/gpu/nvgpu/pmuif/gpmuifperfvfe.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#ifndef _GPMUIFPERFVFE_H_ +#define _GPMUIFPERFVFE_H_ + +#include "gpmuifbios.h" +#include "gpmuifboardobj.h" + +#define CTRL_PERF_VFE_EQU_QUADRATIC_COEFF_COUNT 0x03 +#define NV_PMU_PERF_RPC_VFE_EQU_EVAL_VAR_COUNT_MAX 2 +#define NV_PMU_PERF_RPC_VFE_EQU_MONITOR_COUNT_MAX 16 +#define NV_PMU_VFE_VAR_SINGLE_SENSED_FUSE_SEGMENTS_MAX 1 + +struct nv_pmu_perf_vfe_var_value { + u8 var_type; + u8 reserved[3]; + u32 var_value; +}; + +union nv_pmu_perf_vfe_equ_result { + u32 freq_m_hz; + u32 voltu_v; + u32 vf_gain; + int volt_deltau_v; +}; + +struct nv_pmu_perf_rpc_vfe_equ_eval { + u8 equ_idx; + u8 var_count; + u8 output_type; + struct nv_pmu_perf_vfe_var_value var_values[ + NV_PMU_PERF_RPC_VFE_EQU_EVAL_VAR_COUNT_MAX]; + union nv_pmu_perf_vfe_equ_result result; +}; + +struct nv_pmu_perf_rpc_vfe_load { + bool b_load; +}; + +struct nv_pmu_perf_vfe_var_boardobjgrp_get_status_header { + struct nv_pmu_boardobjgrp_e32 super; +}; + +struct nv_pmu_perf_vfe_var_get_status_super { + struct nv_pmu_boardobj_query board_obj; +}; + +struct nv_pmu_perf_vfe_var_single_sensed_fuse_get_status { + struct nv_pmu_perf_vfe_var_get_status_super super; + u32 fuse_value_integer; + u32 fuse_value_hw_integer; + u8 fuse_version; + bool b_version_check_failed; +}; + +union nv_pmu_perf_vfe_var_boardobj_get_status_union { + struct nv_pmu_boardobj_query board_obj; + struct nv_pmu_perf_vfe_var_get_status_super super; + struct nv_pmu_perf_vfe_var_single_sensed_fuse_get_status fuse_status; +}; + +NV_PMU_BOARDOBJ_GRP_GET_STATUS_MAKE_E32(perf, vfe_var); + +struct nv_pmu_vfe_var { + struct nv_pmu_boardobj super; + u32 out_range_min; + u32 out_range_max; +}; + +struct nv_pmu_vfe_var_derived { + struct nv_pmu_vfe_var super; +}; + +struct nv_pmu_vfe_var_derived_product { + struct nv_pmu_vfe_var_derived super; + u8 var_idx0; + u8 var_idx1; +}; + +struct nv_pmu_vfe_var_derived_sum { + struct nv_pmu_vfe_var_derived super; + u8 var_idx0; + u8 var_idx1; +}; + +struct nv_pmu_vfe_var_single { + struct nv_pmu_vfe_var super; + u8 override_type; + u32 override_value; +}; + +struct nv_pmu_vfe_var_single_frequency { + struct nv_pmu_vfe_var_single super; +}; + +struct nv_pmu_vfe_var_single_sensed { + struct nv_pmu_vfe_var_single super; +}; + +struct nv_pmu_vfe_var_single_sensed_fuse_info { + u8 segment_count; + union nv_pmu_bios_vfield_register_segment segments[ + NV_PMU_VFE_VAR_SINGLE_SENSED_FUSE_SEGMENTS_MAX]; +}; + +struct nv_pmu_vfe_var_single_sensed_fuse_vfield_info { + struct nv_pmu_vfe_var_single_sensed_fuse_info fuse; + u32 fuse_val_default; + int hw_correction_scale; + int hw_correction_offset; + u8 v_field_id; +}; + +struct nv_pmu_vfe_var_single_sensed_fuse_ver_vfield_info { + struct nv_pmu_vfe_var_single_sensed_fuse_info fuse; + u8 ver_expected; + bool b_ver_check; + bool b_use_default_on_ver_check_fail; + u8 v_field_id_ver; +}; + +struct nv_pmu_vfe_var_single_sensed_fuse_override_info { + u32 fuse_val_override; + bool b_fuse_regkey_override; +}; + +struct nv_pmu_vfe_var_single_sensed_fuse { + struct nv_pmu_vfe_var_single_sensed super; + struct nv_pmu_vfe_var_single_sensed_fuse_override_info override_info; + struct nv_pmu_vfe_var_single_sensed_fuse_vfield_info vfield_info; + struct nv_pmu_vfe_var_single_sensed_fuse_ver_vfield_info vfield_ver_info; +}; + +struct nv_pmu_vfe_var_single_sensed_temp { + struct nv_pmu_vfe_var_single_sensed super; + u8 therm_channel_index; + int temp_hysteresis_positive; + int temp_hysteresis_negative; + int temp_default; +}; + +struct nv_pmu_vfe_var_single_voltage { + struct nv_pmu_vfe_var_single super; +}; + +struct nv_pmu_perf_vfe_var_boardobjgrp_set_header { + struct nv_pmu_boardobjgrp_e32 super; + u8 polling_periodms; +}; + +union nv_pmu_perf_vfe_var_boardobj_set_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_vfe_var var; + struct nv_pmu_vfe_var_derived var_derived; + struct nv_pmu_vfe_var_derived_product var_derived_product; + struct nv_pmu_vfe_var_derived_sum var_derived_sum; + struct nv_pmu_vfe_var_single var_single; + struct nv_pmu_vfe_var_single_frequency var_single_frequiency; + struct nv_pmu_vfe_var_single_sensed var_single_sensed; + struct nv_pmu_vfe_var_single_sensed_fuse var_single_sensed_fuse; + struct nv_pmu_vfe_var_single_sensed_temp var_single_sensed_temp; + struct nv_pmu_vfe_var_single_voltage var_single_voltage; +}; + +NV_PMU_BOARDOBJ_GRP_SET_MAKE_E32(perf, vfe_var); + +struct nv_pmu_vfe_equ { + struct nv_pmu_boardobj super; + u8 var_idx; + u8 equ_idx_next; + u8 output_type; + u32 out_range_min; + u32 out_range_max; +}; + +struct nv_pmu_vfe_equ_compare { + struct nv_pmu_vfe_equ super; + u8 func_id; + u8 equ_idx_true; + u8 equ_idx_false; + u32 criteria; +}; + +struct nv_pmu_vfe_equ_minmax { + struct nv_pmu_vfe_equ super; + bool b_max; + u8 equ_idx0; + u8 equ_idx1; +}; + +struct nv_pmu_vfe_equ_quadratic { + struct nv_pmu_vfe_equ super; + u32 coeffs[CTRL_PERF_VFE_EQU_QUADRATIC_COEFF_COUNT]; +}; + +struct nv_pmu_perf_vfe_equ_boardobjgrp_set_header { + struct nv_pmu_boardobjgrp_e255 super; +}; + +union nv_pmu_perf_vfe_equ_boardobj_set_union { + struct nv_pmu_boardobj board_obj; + struct nv_pmu_vfe_equ equ; + struct nv_pmu_vfe_equ_compare equ_comapre; + struct nv_pmu_vfe_equ_minmax equ_minmax; + struct nv_pmu_vfe_equ_quadratic equ_quadratic; +}; + +NV_PMU_BOARDOBJ_GRP_SET_MAKE_E255(perf, vfe_equ); + +#endif /* _GPMUIFPERFVFE_H_*/ diff --git a/drivers/gpu/nvgpu/pmuif/gpmuifvolt.h b/drivers/gpu/nvgpu/pmuif/gpmuifvolt.h new file mode 100644 index 00000000..c480b1cf --- /dev/null +++ b/drivers/gpu/nvgpu/pmuif/gpmuifvolt.h @@ -0,0 +1,33 @@ +/* +* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +*/ +#ifndef _GPMUIFVOLT_H_ +#define _GPMUIFVOLT_H_ + +#include "ctrl/ctrlvolt.h" + +/*! +* Structure containing the number of voltage rails and the list of rail items +* @ref CTRL_PERF_VOLT_RAIL_LIST_ITEM. +*/ +struct nv_pmu_volt_volt_rail_list { + /*! + * Number of VOLT_RAILs that require the voltage change. + */ + u8 num_rails; + /*! + * List of @ref CTRL_PERF_VOLT_RAIL_LIST_ITEM entries. + */ + struct ctrl_perf_volt_rail_list_item rails[2]; +}; + +#endif /* _GPMUIFVOLT_H_*/ -- cgit v1.2.2