diff options
Diffstat (limited to 'meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0691-drm-amd-powerplay-add-SMU-manager-sub-component.patch')
-rw-r--r-- | meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0691-drm-amd-powerplay-add-SMU-manager-sub-component.patch | 670 |
1 files changed, 670 insertions, 0 deletions
diff --git a/meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0691-drm-amd-powerplay-add-SMU-manager-sub-component.patch b/meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0691-drm-amd-powerplay-add-SMU-manager-sub-component.patch new file mode 100644 index 00000000..9a7a5594 --- /dev/null +++ b/meta-amdfalconx86/recipes-kernel/linux/linux-yocto/0691-drm-amd-powerplay-add-SMU-manager-sub-component.patch @@ -0,0 +1,670 @@ +From f672710a1f37cfd5ec7aba5e6b1f633e5344dfb1 Mon Sep 17 00:00:00 2001 +From: Jammy Zhou <Jammy.Zhou@amd.com> +Date: Tue, 21 Jul 2015 17:43:02 +0800 +Subject: [PATCH 0691/1050] drm/amd/powerplay: add SMU manager sub-component + +The SMUMGR is one sub-component of powerplay for SMU firmware support. +The SMU handles firmware loading for other IP blocks (GFX, SDMA, etc.) +on VI parts. The adds the core powerplay infrastructure to handle that. + +v3: direct use printk in powerplay module. +v2: direct use cgs_read/write_register functions in smu-modules + +Signed-off-by: Rex Zhu <Rex.Zhu@amd.com> +Signed-off-by: Jammy Zhou <Jammy.Zhou@amd.com> +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/powerplay/Makefile | 4 + + drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 81 ++++++++ + drivers/gpu/drm/amd/powerplay/inc/pp_instance.h | 33 ++++ + drivers/gpu/drm/amd/powerplay/inc/smumgr.h | 182 +++++++++++++++++ + drivers/gpu/drm/amd/powerplay/smumgr/Makefile | 9 + + drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 251 ++++++++++++++++++++++++ + 6 files changed, 560 insertions(+) + create mode 100644 drivers/gpu/drm/amd/powerplay/inc/pp_instance.h + create mode 100644 drivers/gpu/drm/amd/powerplay/inc/smumgr.h + create mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/Makefile + create mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c + +diff --git a/drivers/gpu/drm/amd/powerplay/Makefile b/drivers/gpu/drm/amd/powerplay/Makefile +index e7428a1..60c6654 100644 +--- a/drivers/gpu/drm/amd/powerplay/Makefile ++++ b/drivers/gpu/drm/amd/powerplay/Makefile +@@ -6,6 +6,10 @@ subdir-ccflags-y += -Iinclude/drm \ + + AMD_PP_PATH = ../powerplay + ++PP_LIBS = smumgr ++ ++AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix drivers/gpu/drm/amd/powerplay/,$(PP_LIBS))) ++ + include $(AMD_POWERPLAY) + + POWER_MGR = amd_powerplay.o +diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +index 39ffc5d..ea78525 100644 +--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c ++++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +@@ -23,8 +23,10 @@ + #include <linux/types.h> + #include <linux/kernel.h> + #include <linux/gfp.h> ++#include <linux/slab.h> + #include "amd_shared.h" + #include "amd_powerplay.h" ++#include "pp_instance.h" + + static int pp_early_init(void *handle) + { +@@ -43,11 +45,51 @@ static int pp_sw_fini(void *handle) + + static int pp_hw_init(void *handle) + { ++ struct pp_instance *pp_handle; ++ struct pp_smumgr *smumgr; ++ int ret = 0; ++ ++ if (handle == NULL) ++ return -EINVAL; ++ ++ pp_handle = (struct pp_instance *)handle; ++ smumgr = pp_handle->smu_mgr; ++ ++ if (smumgr == NULL || smumgr->smumgr_funcs == NULL || ++ smumgr->smumgr_funcs->smu_init == NULL || ++ smumgr->smumgr_funcs->start_smu == NULL) ++ return -EINVAL; ++ ++ ret = smumgr->smumgr_funcs->smu_init(smumgr); ++ if (ret) { ++ printk(KERN_ERR "[ powerplay ] smc initialization failed\n"); ++ return ret; ++ } ++ ++ ret = smumgr->smumgr_funcs->start_smu(smumgr); ++ if (ret) { ++ printk(KERN_ERR "[ powerplay ] smc start failed\n"); ++ smumgr->smumgr_funcs->smu_fini(smumgr); ++ return ret; ++ } + return 0; + } + + static int pp_hw_fini(void *handle) + { ++ struct pp_instance *pp_handle; ++ struct pp_smumgr *smumgr; ++ ++ if (handle == NULL) ++ return -EINVAL; ++ ++ pp_handle = (struct pp_instance *)handle; ++ smumgr = pp_handle->smu_mgr; ++ ++ if (smumgr != NULL || smumgr->smumgr_funcs != NULL || ++ smumgr->smumgr_funcs->smu_fini != NULL) ++ smumgr->smumgr_funcs->smu_fini(smumgr); ++ + return 0; + } + +@@ -176,12 +218,49 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { + .print_current_performance_level = pp_debugfs_print_current_performance_level, + }; + ++static int amd_pp_instance_init(struct amd_pp_init *pp_init, ++ struct amd_powerplay *amd_pp) ++{ ++ int ret; ++ struct pp_instance *handle; ++ ++ handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL); ++ if (handle == NULL) ++ return -ENOMEM; ++ ++ ret = smum_init(pp_init, handle); ++ if (ret) ++ return ret; ++ ++ amd_pp->pp_handle = handle; ++ return 0; ++} ++ ++static int amd_pp_instance_fini(void *handle) ++{ ++ struct pp_instance *instance = (struct pp_instance *)handle; ++ if (instance == NULL) ++ return -EINVAL; ++ ++ smum_fini(instance->smu_mgr); ++ ++ kfree(handle); ++ return 0; ++} ++ + int amd_powerplay_init(struct amd_pp_init *pp_init, + struct amd_powerplay *amd_pp) + { ++ int ret; ++ + if (pp_init == NULL || amd_pp == NULL) + return -EINVAL; + ++ ret = amd_pp_instance_init(pp_init, amd_pp); ++ ++ if (ret) ++ return ret; ++ + amd_pp->ip_funcs = &pp_ip_funcs; + amd_pp->pp_funcs = &pp_dpm_funcs; + +@@ -190,5 +269,7 @@ int amd_powerplay_init(struct amd_pp_init *pp_init, + + int amd_powerplay_fini(void *handle) + { ++ amd_pp_instance_fini(handle); ++ + return 0; + } +diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h +new file mode 100644 +index 0000000..318f827 +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright 2015 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifndef _PP_INSTANCE_H_ ++#define _PP_INSTANCE_H_ ++ ++#include "smumgr.h" ++ ++ ++struct pp_instance { ++ struct pp_smumgr *smu_mgr; ++}; ++ ++#endif +diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +new file mode 100644 +index 0000000..504f035 +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +@@ -0,0 +1,182 @@ ++/* ++ * Copyright 2015 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifndef _SMUMGR_H_ ++#define _SMUMGR_H_ ++#include <linux/types.h> ++#include "pp_instance.h" ++#include "amd_powerplay.h" ++ ++struct pp_smumgr; ++struct pp_instance; ++ ++#define smu_lower_32_bits(n) ((uint32_t)(n)) ++#define smu_upper_32_bits(n) ((uint32_t)(((n)>>16)>>16)) ++ ++struct pp_smumgr_func { ++ int (*smu_init)(struct pp_smumgr *smumgr); ++ int (*smu_fini)(struct pp_smumgr *smumgr); ++ int (*start_smu)(struct pp_smumgr *smumgr); ++ int (*check_fw_load_finish)(struct pp_smumgr *smumgr, ++ uint32_t firmware); ++ int (*request_smu_load_fw)(struct pp_smumgr *smumgr); ++ int (*request_smu_load_specific_fw)(struct pp_smumgr *smumgr, ++ uint32_t firmware); ++ int (*get_argument)(struct pp_smumgr *smumgr); ++ int (*send_msg_to_smc)(struct pp_smumgr *smumgr, uint16_t msg); ++ int (*send_msg_to_smc_with_parameter)(struct pp_smumgr *smumgr, ++ uint16_t msg, uint32_t parameter); ++ int (*download_pptable_settings)(struct pp_smumgr *smumgr, ++ void **table); ++ int (*upload_pptable_settings)(struct pp_smumgr *smumgr); ++}; ++ ++struct pp_smumgr { ++ uint32_t chip_family; ++ uint32_t chip_id; ++ uint32_t hw_revision; ++ void *device; ++ void *backend; ++ uint32_t usec_timeout; ++ bool reload_fw; ++ const struct pp_smumgr_func *smumgr_funcs; ++}; ++ ++ ++extern int smum_init(struct amd_pp_init *pp_init, ++ struct pp_instance *handle); ++ ++extern int smum_fini(struct pp_smumgr *smumgr); ++ ++extern int smum_get_argument(struct pp_smumgr *smumgr); ++ ++extern int smum_download_powerplay_table(struct pp_smumgr *smumgr, void **table); ++ ++extern int smum_upload_powerplay_table(struct pp_smumgr *smumgr); ++ ++extern int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg); ++ ++extern int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, ++ uint16_t msg, uint32_t parameter); ++ ++extern int smum_wait_on_register(struct pp_smumgr *smumgr, ++ uint32_t index, uint32_t value, uint32_t mask); ++ ++extern int smum_wait_for_register_unequal(struct pp_smumgr *smumgr, ++ uint32_t index, uint32_t value, uint32_t mask); ++ ++extern int smum_wait_on_indirect_register(struct pp_smumgr *smumgr, ++ uint32_t indirect_port, uint32_t index, ++ uint32_t value, uint32_t mask); ++ ++ ++extern void smum_wait_for_indirect_register_unequal( ++ struct pp_smumgr *smumgr, ++ uint32_t indirect_port, uint32_t index, ++ uint32_t value, uint32_t mask); ++ ++extern int smu_allocate_memory(void *device, uint32_t size, ++ enum cgs_gpu_mem_type type, ++ uint32_t byte_align, uint64_t *mc_addr, ++ void **kptr, void *handle); ++ ++extern int smu_free_memory(void *device, void *handle); ++ ++#define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT ++ ++#define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK ++ ++#define SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \ ++ port, index, value, mask) \ ++ smum_wait_on_indirect_register(smumgr, \ ++ mm##port##_INDEX, index, value, mask) ++ ++ ++#define SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ ++ index, value, mask) \ ++ smum_wait_for_register_unequal(smumgr, \ ++ index, value, mask) ++ ++#define SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, value, mask) \ ++ SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ ++ mm##reg, value, mask) ++ ++#define SMUM_WAIT_FIELD_UNEQUAL(smumgr, reg, field, fieldval) \ ++ SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, \ ++ (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ ++ SMUM_FIELD_MASK(reg, field)) ++ ++#define SMUM_GET_FIELD(value, reg, field) \ ++ (((value) & SMUM_FIELD_MASK(reg, field)) \ ++ >> SMUM_FIELD_SHIFT(reg, field)) ++ ++#define SMUM_READ_FIELD(device, reg, field) \ ++ SMUM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) ++ ++#define SMUM_SET_FIELD(value, reg, field, field_val) \ ++ (((value) & ~SMUM_FIELD_MASK(reg, field)) | \ ++ (SMUM_FIELD_MASK(reg, field) & ((field_val) << \ ++ SMUM_FIELD_SHIFT(reg, field)))) ++ ++#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \ ++ port, index, value, mask) \ ++ smum_wait_on_indirect_register(smumgr, \ ++ mm##port##_INDEX_0, index, value, mask) ++ ++#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ ++ port, index, value, mask) \ ++ smum_wait_for_indirect_register_unequal(smumgr, \ ++ mm##port##_INDEX_0, index, value, mask) ++ ++ ++#define SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \ ++ SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) ++ ++#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \ ++ SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) ++ ++ ++/*Operations on named fields.*/ ++ ++#define SMUM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ ++ SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ ++ reg, field) ++ ++#define SMUM_WRITE_FIELD(device, reg, field, fieldval) \ ++ cgs_write_register(device, mm##reg, \ ++ SMUM_SET_FIELD(cgs_read_register(device, mm##reg), reg, field, fieldval)) ++ ++#define SMUM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ ++ cgs_write_ind_register(device, port, ix##reg, \ ++ SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ ++ reg, field, fieldval)) ++ ++#define SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \ ++ SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, \ ++ (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ ++ SMUM_FIELD_MASK(reg, field)) ++ ++#define SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \ ++ SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, \ ++ (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ ++ SMUM_FIELD_MASK(reg, field)) ++#endif +diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile +new file mode 100644 +index 0000000..61bfb2a +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile +@@ -0,0 +1,9 @@ ++# ++# Makefile for the 'smu manager' sub-component of powerplay. ++# It provides the smu management services for the driver. ++ ++SMU_MGR = smumgr.o ++ ++AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR)) ++ ++AMD_POWERPLAY_FILES += $(AMD_PP_SMUMGR) +diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +new file mode 100644 +index 0000000..1a11714 +--- /dev/null ++++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +@@ -0,0 +1,251 @@ ++/* ++ * Copyright 2015 Advanced Micro Devices, Inc. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a ++ * copy of this software and associated documentation files (the "Software"), ++ * to deal in the Software without restriction, including without limitation ++ * the rights to use, copy, modify, merge, publish, distribute, sublicense, ++ * and/or sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include "pp_instance.h" ++#include "smumgr.h" ++#include "cgs_common.h" ++#include "linux/delay.h" ++ ++int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) ++{ ++ struct pp_smumgr *smumgr; ++ ++ if ((handle == NULL) || (pp_init == NULL)) ++ return -EINVAL; ++ ++ smumgr = kzalloc(sizeof(struct pp_smumgr), GFP_KERNEL); ++ if (smumgr == NULL) ++ return -ENOMEM; ++ ++ smumgr->device = pp_init->device; ++ smumgr->chip_family = pp_init->chip_family; ++ smumgr->chip_id = pp_init->chip_id; ++ smumgr->hw_revision = pp_init->rev_id; ++ smumgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; ++ smumgr->reload_fw = 1; ++ handle->smu_mgr = smumgr; ++ ++ switch (smumgr->chip_family) { ++ case AMD_FAMILY_CZ: ++ /* TODO */ ++ break; ++ case AMD_FAMILY_VI: ++ /* TODO */ ++ break; ++ default: ++ kfree(smumgr); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++int smum_fini(struct pp_smumgr *smumgr) ++{ ++ kfree(smumgr); ++ return 0; ++} ++ ++int smum_get_argument(struct pp_smumgr *smumgr) ++{ ++ if (NULL != smumgr->smumgr_funcs->get_argument) ++ return smumgr->smumgr_funcs->get_argument(smumgr); ++ ++ return 0; ++} ++ ++int smum_download_powerplay_table(struct pp_smumgr *smumgr, ++ void **table) ++{ ++ if (NULL != smumgr->smumgr_funcs->download_pptable_settings) ++ return smumgr->smumgr_funcs->download_pptable_settings(smumgr, ++ table); ++ ++ return 0; ++} ++ ++int smum_upload_powerplay_table(struct pp_smumgr *smumgr) ++{ ++ if (NULL != smumgr->smumgr_funcs->upload_pptable_settings) ++ return smumgr->smumgr_funcs->upload_pptable_settings(smumgr); ++ ++ return 0; ++} ++ ++int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) ++{ ++ if (smumgr == NULL || smumgr->smumgr_funcs->send_msg_to_smc == NULL) ++ return -EINVAL; ++ ++ return smumgr->smumgr_funcs->send_msg_to_smc(smumgr, msg); ++} ++ ++int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, ++ uint16_t msg, uint32_t parameter) ++{ ++ if (smumgr == NULL || ++ smumgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL) ++ return -EINVAL; ++ return smumgr->smumgr_funcs->send_msg_to_smc_with_parameter( ++ smumgr, msg, parameter); ++} ++ ++/* ++ * Returns once the part of the register indicated by the mask has ++ * reached the given value. ++ */ ++int smum_wait_on_register(struct pp_smumgr *smumgr, ++ uint32_t index, ++ uint32_t value, uint32_t mask) ++{ ++ uint32_t i; ++ uint32_t cur_value; ++ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ for (i = 0; i < smumgr->usec_timeout; i++) { ++ cur_value = cgs_read_register(smumgr->device, index); ++ if ((cur_value & mask) == (value & mask)) ++ break; ++ udelay(1); ++ } ++ ++ /* timeout means wrong logic*/ ++ if (i == smumgr->usec_timeout) ++ return -1; ++ ++ return 0; ++} ++ ++int smum_wait_for_register_unequal(struct pp_smumgr *smumgr, ++ uint32_t index, ++ uint32_t value, uint32_t mask) ++{ ++ uint32_t i; ++ uint32_t cur_value; ++ ++ if (smumgr == NULL) ++ return -EINVAL; ++ ++ for (i = 0; i < smumgr->usec_timeout; i++) { ++ cur_value = cgs_read_register(smumgr->device, ++ index); ++ if ((cur_value & mask) != (value & mask)) ++ break; ++ udelay(1); ++ } ++ ++ /* timeout means wrong logic */ ++ if (i == smumgr->usec_timeout) ++ return -1; ++ ++ return 0; ++} ++ ++ ++/* ++ * Returns once the part of the register indicated by the mask ++ * has reached the given value.The indirect space is described by ++ * giving the memory-mapped index of the indirect index register. ++ */ ++int smum_wait_on_indirect_register(struct pp_smumgr *smumgr, ++ uint32_t indirect_port, ++ uint32_t index, ++ uint32_t value, ++ uint32_t mask) ++{ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return -EINVAL; ++ ++ cgs_write_register(smumgr->device, indirect_port, index); ++ return smum_wait_on_register(smumgr, indirect_port + 1, ++ mask, value); ++} ++ ++void smum_wait_for_indirect_register_unequal( ++ struct pp_smumgr *smumgr, ++ uint32_t indirect_port, ++ uint32_t index, ++ uint32_t value, ++ uint32_t mask) ++{ ++ if (smumgr == NULL || smumgr->device == NULL) ++ return; ++ cgs_write_register(smumgr->device, indirect_port, index); ++ smum_wait_for_register_unequal(smumgr, indirect_port + 1, ++ value, mask); ++} ++ ++int smu_allocate_memory(void *device, uint32_t size, ++ enum cgs_gpu_mem_type type, ++ uint32_t byte_align, uint64_t *mc_addr, ++ void **kptr, void *handle) ++{ ++ int ret = 0; ++ cgs_handle_t cgs_handle; ++ ++ if (device == NULL || handle == NULL || ++ mc_addr == NULL || kptr == NULL) ++ return -EINVAL; ++ ++ ret = cgs_alloc_gpu_mem(device, type, size, byte_align, ++ 0, 0, (cgs_handle_t *)handle); ++ if (ret) ++ return -ENOMEM; ++ ++ cgs_handle = *(cgs_handle_t *)handle; ++ ++ ret = cgs_gmap_gpu_mem(device, cgs_handle, mc_addr); ++ if (ret) ++ goto error_gmap; ++ ++ ret = cgs_kmap_gpu_mem(device, cgs_handle, kptr); ++ if (ret) ++ goto error_kmap; ++ ++ return 0; ++ ++error_kmap: ++ cgs_gunmap_gpu_mem(device, cgs_handle); ++ ++error_gmap: ++ cgs_free_gpu_mem(device, cgs_handle); ++ return ret; ++} ++ ++int smu_free_memory(void *device, void *handle) ++{ ++ cgs_handle_t cgs_handle = (cgs_handle_t)handle; ++ ++ if (device == NULL || handle == NULL) ++ return -EINVAL; ++ ++ cgs_kunmap_gpu_mem(device, cgs_handle); ++ cgs_gunmap_gpu_mem(device, cgs_handle); ++ cgs_free_gpu_mem(device, cgs_handle); ++ ++ return 0; ++} +-- +1.9.1 + |