140a684f9SVinay Belgaumkar // SPDX-License-Identifier: MIT 240a684f9SVinay Belgaumkar /* 340a684f9SVinay Belgaumkar * Copyright © 2026 Intel Corporation 440a684f9SVinay Belgaumkar */ 540a684f9SVinay Belgaumkar 640a684f9SVinay Belgaumkar #include <drm/drm_print.h> 740a684f9SVinay Belgaumkar 840a684f9SVinay Belgaumkar #include "abi/guc_actions_slpc_abi.h" 940a684f9SVinay Belgaumkar #include "xe_device.h" 1040a684f9SVinay Belgaumkar #include "xe_force_wake.h" 1140a684f9SVinay Belgaumkar #include "xe_gt.h" 1240a684f9SVinay Belgaumkar #include "xe_gt_idle.h" 1340a684f9SVinay Belgaumkar #include "xe_gt_printk.h" 1440a684f9SVinay Belgaumkar #include "xe_guc.h" 1540a684f9SVinay Belgaumkar #include "xe_guc_ct.h" 16*fabedb75SVinay Belgaumkar #include "xe_guc_pc.h" 1740a684f9SVinay Belgaumkar #include "xe_guc_rc.h" 1840a684f9SVinay Belgaumkar #include "xe_pm.h" 1940a684f9SVinay Belgaumkar 2040a684f9SVinay Belgaumkar /** 2140a684f9SVinay Belgaumkar * DOC: GuC RC (Render C-states) 2240a684f9SVinay Belgaumkar * 2340a684f9SVinay Belgaumkar * GuC handles the GT transition to deeper C-states in conjunction with Pcode. 2440a684f9SVinay Belgaumkar * GuC RC can be enabled independently of the frequency component in SLPC, 2540a684f9SVinay Belgaumkar * which is also controlled by GuC. 2640a684f9SVinay Belgaumkar * 2740a684f9SVinay Belgaumkar * This file will contain all H2G related logic for handling Render C-states. 2840a684f9SVinay Belgaumkar * There are some calls to xe_gt_idle, where we enable host C6 when GuC RC is 2940a684f9SVinay Belgaumkar * skipped. GuC RC is mostly independent of xe_guc_pc with the exception of 3040a684f9SVinay Belgaumkar * functions that override the mode for which we have to rely on the SLPC H2G 3140a684f9SVinay Belgaumkar * calls. 3240a684f9SVinay Belgaumkar */ 3340a684f9SVinay Belgaumkar 3440a684f9SVinay Belgaumkar static int guc_action_setup_gucrc(struct xe_guc *guc, u32 control) 3540a684f9SVinay Belgaumkar { 3640a684f9SVinay Belgaumkar u32 action[] = { 3740a684f9SVinay Belgaumkar GUC_ACTION_HOST2GUC_SETUP_PC_GUCRC, 3840a684f9SVinay Belgaumkar control, 3940a684f9SVinay Belgaumkar }; 4040a684f9SVinay Belgaumkar int ret; 4140a684f9SVinay Belgaumkar 4240a684f9SVinay Belgaumkar ret = xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0); 4340a684f9SVinay Belgaumkar if (ret && !(xe_device_wedged(guc_to_xe(guc)) && ret == -ECANCELED)) 4440a684f9SVinay Belgaumkar xe_gt_err(guc_to_gt(guc), 4540a684f9SVinay Belgaumkar "GuC RC setup %s(%u) failed (%pe)\n", 4640a684f9SVinay Belgaumkar control == GUCRC_HOST_CONTROL ? "HOST_CONTROL" : 4740a684f9SVinay Belgaumkar control == GUCRC_FIRMWARE_CONTROL ? "FIRMWARE_CONTROL" : 4840a684f9SVinay Belgaumkar "UNKNOWN", control, ERR_PTR(ret)); 4940a684f9SVinay Belgaumkar return ret; 5040a684f9SVinay Belgaumkar } 5140a684f9SVinay Belgaumkar 5240a684f9SVinay Belgaumkar /** 5340a684f9SVinay Belgaumkar * xe_guc_rc_disable() - Disable GuC RC 5440a684f9SVinay Belgaumkar * @guc: Xe GuC instance 5540a684f9SVinay Belgaumkar * 5640a684f9SVinay Belgaumkar * Disables GuC RC by taking control of RC6 back from GuC. 5740a684f9SVinay Belgaumkar */ 5840a684f9SVinay Belgaumkar void xe_guc_rc_disable(struct xe_guc *guc) 5940a684f9SVinay Belgaumkar { 6040a684f9SVinay Belgaumkar struct xe_device *xe = guc_to_xe(guc); 6140a684f9SVinay Belgaumkar struct xe_gt *gt = guc_to_gt(guc); 6240a684f9SVinay Belgaumkar 6340a684f9SVinay Belgaumkar if (!xe->info.skip_guc_pc && xe->info.platform != XE_PVC) 6440a684f9SVinay Belgaumkar if (guc_action_setup_gucrc(guc, GUCRC_HOST_CONTROL)) 6540a684f9SVinay Belgaumkar return; 6640a684f9SVinay Belgaumkar 6740a684f9SVinay Belgaumkar xe_gt_WARN_ON(gt, xe_gt_idle_disable_c6(gt)); 6840a684f9SVinay Belgaumkar } 6940a684f9SVinay Belgaumkar 7040a684f9SVinay Belgaumkar static void xe_guc_rc_fini_hw(void *arg) 7140a684f9SVinay Belgaumkar { 7240a684f9SVinay Belgaumkar struct xe_guc *guc = arg; 7340a684f9SVinay Belgaumkar struct xe_device *xe = guc_to_xe(guc); 7440a684f9SVinay Belgaumkar struct xe_gt *gt = guc_to_gt(guc); 7540a684f9SVinay Belgaumkar 7640a684f9SVinay Belgaumkar if (xe_device_wedged(xe)) 7740a684f9SVinay Belgaumkar return; 7840a684f9SVinay Belgaumkar 7940a684f9SVinay Belgaumkar CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); 8040a684f9SVinay Belgaumkar xe_guc_rc_disable(guc); 8140a684f9SVinay Belgaumkar } 8240a684f9SVinay Belgaumkar 8340a684f9SVinay Belgaumkar /** 8440a684f9SVinay Belgaumkar * xe_guc_rc_init() - Init GuC RC 8540a684f9SVinay Belgaumkar * @guc: Xe GuC instance 8640a684f9SVinay Belgaumkar * 8740a684f9SVinay Belgaumkar * Add callback action for GuC RC 8840a684f9SVinay Belgaumkar * 8940a684f9SVinay Belgaumkar * Return: 0 on success, negative error code on error. 9040a684f9SVinay Belgaumkar */ 9140a684f9SVinay Belgaumkar int xe_guc_rc_init(struct xe_guc *guc) 9240a684f9SVinay Belgaumkar { 9340a684f9SVinay Belgaumkar struct xe_device *xe = guc_to_xe(guc); 9440a684f9SVinay Belgaumkar struct xe_gt *gt = guc_to_gt(guc); 9540a684f9SVinay Belgaumkar 9640a684f9SVinay Belgaumkar xe_gt_assert(gt, xe_device_uc_enabled(xe)); 9740a684f9SVinay Belgaumkar 9840a684f9SVinay Belgaumkar return devm_add_action_or_reset(xe->drm.dev, xe_guc_rc_fini_hw, guc); 9940a684f9SVinay Belgaumkar } 10040a684f9SVinay Belgaumkar 10140a684f9SVinay Belgaumkar /** 10240a684f9SVinay Belgaumkar * xe_guc_rc_enable() - Enable GuC RC feature if applicable 10340a684f9SVinay Belgaumkar * @guc: Xe GuC instance 10440a684f9SVinay Belgaumkar * 10540a684f9SVinay Belgaumkar * Enables GuC RC feature. 10640a684f9SVinay Belgaumkar * 10740a684f9SVinay Belgaumkar * Return: 0 on success, negative error code on error. 10840a684f9SVinay Belgaumkar */ 10940a684f9SVinay Belgaumkar int xe_guc_rc_enable(struct xe_guc *guc) 11040a684f9SVinay Belgaumkar { 11140a684f9SVinay Belgaumkar struct xe_device *xe = guc_to_xe(guc); 11240a684f9SVinay Belgaumkar struct xe_gt *gt = guc_to_gt(guc); 11340a684f9SVinay Belgaumkar 11440a684f9SVinay Belgaumkar xe_gt_assert(gt, xe_device_uc_enabled(xe)); 11540a684f9SVinay Belgaumkar 11640a684f9SVinay Belgaumkar CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT); 11740a684f9SVinay Belgaumkar if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT)) 11840a684f9SVinay Belgaumkar return -ETIMEDOUT; 11940a684f9SVinay Belgaumkar 12040a684f9SVinay Belgaumkar if (xe->info.platform == XE_PVC) { 12140a684f9SVinay Belgaumkar xe_guc_rc_disable(guc); 12240a684f9SVinay Belgaumkar return 0; 12340a684f9SVinay Belgaumkar } 12440a684f9SVinay Belgaumkar 12540a684f9SVinay Belgaumkar if (xe->info.skip_guc_pc) { 12640a684f9SVinay Belgaumkar xe_gt_idle_enable_c6(gt); 12740a684f9SVinay Belgaumkar return 0; 12840a684f9SVinay Belgaumkar } 12940a684f9SVinay Belgaumkar 13040a684f9SVinay Belgaumkar return guc_action_setup_gucrc(guc, GUCRC_FIRMWARE_CONTROL); 13140a684f9SVinay Belgaumkar } 132