xref: /openbmc/linux/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c (revision 301306a9)
1 /*
2  * Copyright 2020 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #define SWSMU_CODE_LAYER_L4
24 
25 #include "amdgpu.h"
26 #include "amdgpu_smu.h"
27 #include "smu_cmn.h"
28 #include "soc15_common.h"
29 
30 /*
31  * DO NOT use these for err/warn/info/debug messages.
32  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
33  * They are more MGPU friendly.
34  */
35 #undef pr_err
36 #undef pr_warn
37 #undef pr_info
38 #undef pr_debug
39 
40 /*
41  * Although these are defined in each ASIC's specific header file.
42  * They share the same definitions and values. That makes common
43  * APIs for SMC messages issuing for all ASICs possible.
44  */
45 #define mmMP1_SMN_C2PMSG_66                                                                            0x0282
46 #define mmMP1_SMN_C2PMSG_66_BASE_IDX                                                                   0
47 
48 #define mmMP1_SMN_C2PMSG_82                                                                            0x0292
49 #define mmMP1_SMN_C2PMSG_82_BASE_IDX                                                                   0
50 
51 #define mmMP1_SMN_C2PMSG_90                                                                            0x029a
52 #define mmMP1_SMN_C2PMSG_90_BASE_IDX                                                                   0
53 
54 /* SMU 13.0.5 has its specific mailbox messaging registers */
55 
56 #define mmMP1_C2PMSG_2                                                                            (0xbee142 + 0xb00000 / 4)
57 #define mmMP1_C2PMSG_2_BASE_IDX                                                                   0
58 
59 #define mmMP1_C2PMSG_34                                                                           (0xbee262 + 0xb00000 / 4)
60 #define mmMP1_C2PMSG_34_BASE_IDX                                                                   0
61 
62 #define mmMP1_C2PMSG_33                                                                                (0xbee261 + 0xb00000 / 4)
63 #define mmMP1_C2PMSG_33_BASE_IDX                                                                   0
64 
65 #define MP1_C2PMSG_90__CONTENT_MASK                                                                    0xFFFFFFFFL
66 
67 #undef __SMU_DUMMY_MAP
68 #define __SMU_DUMMY_MAP(type)	#type
69 static const char * const __smu_message_names[] = {
70 	SMU_MESSAGE_TYPES
71 };
72 
73 #define smu_cmn_call_asic_func(intf, smu, args...)                             \
74 	((smu)->ppt_funcs ? ((smu)->ppt_funcs->intf ?                          \
75 				     (smu)->ppt_funcs->intf(smu, ##args) :     \
76 				     -ENOTSUPP) :                              \
77 			    -EINVAL)
78 
79 static const char *smu_get_message_name(struct smu_context *smu,
80 					enum smu_message_type type)
81 {
82 	if (type < 0 || type >= SMU_MSG_MAX_COUNT)
83 		return "unknown smu message";
84 
85 	return __smu_message_names[type];
86 }
87 
88 static void smu_cmn_read_arg(struct smu_context *smu,
89 			     uint32_t *arg)
90 {
91 	struct amdgpu_device *adev = smu->adev;
92 
93 	if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 5))
94 		*arg = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_34);
95 	else
96 		*arg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
97 }
98 
99 /* Redefine the SMU error codes here.
100  *
101  * Note that these definitions are redundant and should be removed
102  * when the SMU has exported a unified header file containing these
103  * macros, which header file we can just include and use the SMU's
104  * macros. At the moment, these error codes are defined by the SMU
105  * per-ASIC unfortunately, yet we're a one driver for all ASICs.
106  */
107 #define SMU_RESP_NONE           0
108 #define SMU_RESP_OK             1
109 #define SMU_RESP_CMD_FAIL       0xFF
110 #define SMU_RESP_CMD_UNKNOWN    0xFE
111 #define SMU_RESP_CMD_BAD_PREREQ 0xFD
112 #define SMU_RESP_BUSY_OTHER     0xFC
113 #define SMU_RESP_DEBUG_END      0xFB
114 
115 /**
116  * __smu_cmn_poll_stat -- poll for a status from the SMU
117  * @smu: a pointer to SMU context
118  *
119  * Returns the status of the SMU, which could be,
120  *    0, the SMU is busy with your command;
121  *    1, execution status: success, execution result: success;
122  * 0xFF, execution status: success, execution result: failure;
123  * 0xFE, unknown command;
124  * 0xFD, valid command, but bad (command) prerequisites;
125  * 0xFC, the command was rejected as the SMU is busy;
126  * 0xFB, "SMC_Result_DebugDataDumpEnd".
127  *
128  * The values here are not defined by macros, because I'd rather we
129  * include a single header file which defines them, which is
130  * maintained by the SMU FW team, so that we're impervious to firmware
131  * changes. At the moment those values are defined in various header
132  * files, one for each ASIC, yet here we're a single ASIC-agnostic
133  * interface. Such a change can be followed-up by a subsequent patch.
134  */
135 static u32 __smu_cmn_poll_stat(struct smu_context *smu)
136 {
137 	struct amdgpu_device *adev = smu->adev;
138 	int timeout = adev->usec_timeout * 20;
139 	u32 reg;
140 
141 	for ( ; timeout > 0; timeout--) {
142 		if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 5))
143 			reg = RREG32_SOC15(MP1, 0, mmMP1_C2PMSG_33);
144 		else
145 			reg = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
146 		if ((reg & MP1_C2PMSG_90__CONTENT_MASK) != 0)
147 			break;
148 
149 		udelay(1);
150 	}
151 
152 	return reg;
153 }
154 
155 static void __smu_cmn_reg_print_error(struct smu_context *smu,
156 				      u32 reg_c2pmsg_90,
157 				      int msg_index,
158 				      u32 param,
159 				      enum smu_message_type msg)
160 {
161 	struct amdgpu_device *adev = smu->adev;
162 	const char *message = smu_get_message_name(smu, msg);
163 
164 	switch (reg_c2pmsg_90) {
165 	case SMU_RESP_NONE: {
166 		u32 msg_idx = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66);
167 		u32 prm     = RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
168 		dev_err_ratelimited(adev->dev,
169 				    "SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x%08X SMN_C2PMSG_82:0x%08X",
170 				    msg_idx, prm);
171 	}
172 		break;
173 	case SMU_RESP_OK:
174 		/* The SMU executed the command. It completed with a
175 		 * successful result.
176 		 */
177 		break;
178 	case SMU_RESP_CMD_FAIL:
179 		/* The SMU executed the command. It completed with an
180 		 * unsuccessful result.
181 		 */
182 		break;
183 	case SMU_RESP_CMD_UNKNOWN:
184 		dev_err_ratelimited(adev->dev,
185 				    "SMU: unknown command: index:%d param:0x%08X message:%s",
186 				    msg_index, param, message);
187 		break;
188 	case SMU_RESP_CMD_BAD_PREREQ:
189 		dev_err_ratelimited(adev->dev,
190 				    "SMU: valid command, bad prerequisites: index:%d param:0x%08X message:%s",
191 				    msg_index, param, message);
192 		break;
193 	case SMU_RESP_BUSY_OTHER:
194 		dev_err_ratelimited(adev->dev,
195 				    "SMU: I'm very busy for your command: index:%d param:0x%08X message:%s",
196 				    msg_index, param, message);
197 		break;
198 	case SMU_RESP_DEBUG_END:
199 		dev_err_ratelimited(adev->dev,
200 				    "SMU: I'm debugging!");
201 		break;
202 	default:
203 		dev_err_ratelimited(adev->dev,
204 				    "SMU: response:0x%08X for index:%d param:0x%08X message:%s?",
205 				    reg_c2pmsg_90, msg_index, param, message);
206 		break;
207 	}
208 }
209 
210 static int __smu_cmn_reg2errno(struct smu_context *smu, u32 reg_c2pmsg_90)
211 {
212 	int res;
213 
214 	switch (reg_c2pmsg_90) {
215 	case SMU_RESP_NONE:
216 		/* The SMU is busy--still executing your command.
217 		 */
218 		res = -ETIME;
219 		break;
220 	case SMU_RESP_OK:
221 		res = 0;
222 		break;
223 	case SMU_RESP_CMD_FAIL:
224 		/* Command completed successfully, but the command
225 		 * status was failure.
226 		 */
227 		res = -EIO;
228 		break;
229 	case SMU_RESP_CMD_UNKNOWN:
230 		/* Unknown command--ignored by the SMU.
231 		 */
232 		res = -EOPNOTSUPP;
233 		break;
234 	case SMU_RESP_CMD_BAD_PREREQ:
235 		/* Valid command--bad prerequisites.
236 		 */
237 		res = -EINVAL;
238 		break;
239 	case SMU_RESP_BUSY_OTHER:
240 		/* The SMU is busy with other commands. The client
241 		 * should retry in 10 us.
242 		 */
243 		res = -EBUSY;
244 		break;
245 	default:
246 		/* Unknown or debug response from the SMU.
247 		 */
248 		res = -EREMOTEIO;
249 		break;
250 	}
251 
252 	return res;
253 }
254 
255 static void __smu_cmn_send_msg(struct smu_context *smu,
256 			       u16 msg,
257 			       u32 param)
258 {
259 	struct amdgpu_device *adev = smu->adev;
260 
261 	if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 5)) {
262 		WREG32_SOC15(MP1, 0, mmMP1_C2PMSG_33, 0);
263 		WREG32_SOC15(MP1, 0, mmMP1_C2PMSG_34, param);
264 		WREG32_SOC15(MP1, 0, mmMP1_C2PMSG_2, msg);
265 	} else {
266 		WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
267 		WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, param);
268 		WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
269 	}
270 
271 }
272 
273 /**
274  * smu_cmn_send_msg_without_waiting -- send the message; don't wait for status
275  * @smu: pointer to an SMU context
276  * @msg_index: message index
277  * @param: message parameter to send to the SMU
278  *
279  * Send a message to the SMU with the parameter passed. Do not wait
280  * for status/result of the message, thus the "without_waiting".
281  *
282  * Return 0 on success, -errno on error if we weren't able to _send_
283  * the message for some reason. See __smu_cmn_reg2errno() for details
284  * of the -errno.
285  */
286 int smu_cmn_send_msg_without_waiting(struct smu_context *smu,
287 				     uint16_t msg_index,
288 				     uint32_t param)
289 {
290 	struct amdgpu_device *adev = smu->adev;
291 	u32 reg;
292 	int res;
293 
294 	if (adev->no_hw_access)
295 		return 0;
296 
297 	reg = __smu_cmn_poll_stat(smu);
298 	res = __smu_cmn_reg2errno(smu, reg);
299 	if (reg == SMU_RESP_NONE ||
300 	    reg == SMU_RESP_BUSY_OTHER ||
301 	    res == -EREMOTEIO)
302 		goto Out;
303 	__smu_cmn_send_msg(smu, msg_index, param);
304 	res = 0;
305 Out:
306 	if (unlikely(adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) &&
307 	    res && (res != -ETIME)) {
308 		amdgpu_device_halt(adev);
309 		WARN_ON(1);
310 	}
311 
312 	return res;
313 }
314 
315 /**
316  * smu_cmn_wait_for_response -- wait for response from the SMU
317  * @smu: pointer to an SMU context
318  *
319  * Wait for status from the SMU.
320  *
321  * Return 0 on success, -errno on error, indicating the execution
322  * status and result of the message being waited for. See
323  * __smu_cmn_reg2errno() for details of the -errno.
324  */
325 int smu_cmn_wait_for_response(struct smu_context *smu)
326 {
327 	u32 reg;
328 	int res;
329 
330 	reg = __smu_cmn_poll_stat(smu);
331 	res = __smu_cmn_reg2errno(smu, reg);
332 
333 	if (unlikely(smu->adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) &&
334 	    res && (res != -ETIME)) {
335 		amdgpu_device_halt(smu->adev);
336 		WARN_ON(1);
337 	}
338 
339 	return res;
340 }
341 
342 /**
343  * smu_cmn_send_smc_msg_with_param -- send a message with parameter
344  * @smu: pointer to an SMU context
345  * @msg: message to send
346  * @param: parameter to send to the SMU
347  * @read_arg: pointer to u32 to return a value from the SMU back
348  *            to the caller
349  *
350  * Send the message @msg with parameter @param to the SMU, wait for
351  * completion of the command, and return back a value from the SMU in
352  * @read_arg pointer.
353  *
354  * Return 0 on success, -errno on error, if we weren't able to send
355  * the message or if the message completed with some kind of
356  * error. See __smu_cmn_reg2errno() for details of the -errno.
357  *
358  * If we weren't able to send the message to the SMU, we also print
359  * the error to the standard log.
360  *
361  * Command completion status is printed only if the -errno is
362  * -EREMOTEIO, indicating that the SMU returned back an
363  * undefined/unknown/unspecified result. All other cases are
364  * well-defined, not printed, but instead given back to the client to
365  * decide what further to do.
366  *
367  * The return value, @read_arg is read back regardless, to give back
368  * more information to the client, which on error would most likely be
369  * @param, but we can't assume that. This also eliminates more
370  * conditionals.
371  */
372 int smu_cmn_send_smc_msg_with_param(struct smu_context *smu,
373 				    enum smu_message_type msg,
374 				    uint32_t param,
375 				    uint32_t *read_arg)
376 {
377 	struct amdgpu_device *adev = smu->adev;
378 	int res, index;
379 	u32 reg;
380 
381 	if (adev->no_hw_access)
382 		return 0;
383 
384 	index = smu_cmn_to_asic_specific_index(smu,
385 					       CMN2ASIC_MAPPING_MSG,
386 					       msg);
387 	if (index < 0)
388 		return index == -EACCES ? 0 : index;
389 
390 	mutex_lock(&smu->message_lock);
391 	reg = __smu_cmn_poll_stat(smu);
392 	res = __smu_cmn_reg2errno(smu, reg);
393 	if (reg == SMU_RESP_NONE ||
394 	    reg == SMU_RESP_BUSY_OTHER ||
395 	    res == -EREMOTEIO) {
396 		__smu_cmn_reg_print_error(smu, reg, index, param, msg);
397 		goto Out;
398 	}
399 	__smu_cmn_send_msg(smu, (uint16_t) index, param);
400 	reg = __smu_cmn_poll_stat(smu);
401 	res = __smu_cmn_reg2errno(smu, reg);
402 	if (res != 0)
403 		__smu_cmn_reg_print_error(smu, reg, index, param, msg);
404 	if (read_arg)
405 		smu_cmn_read_arg(smu, read_arg);
406 Out:
407 	if (unlikely(adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) && res) {
408 		amdgpu_device_halt(adev);
409 		WARN_ON(1);
410 	}
411 
412 	mutex_unlock(&smu->message_lock);
413 	return res;
414 }
415 
416 int smu_cmn_send_smc_msg(struct smu_context *smu,
417 			 enum smu_message_type msg,
418 			 uint32_t *read_arg)
419 {
420 	return smu_cmn_send_smc_msg_with_param(smu,
421 					       msg,
422 					       0,
423 					       read_arg);
424 }
425 
426 int smu_cmn_to_asic_specific_index(struct smu_context *smu,
427 				   enum smu_cmn2asic_mapping_type type,
428 				   uint32_t index)
429 {
430 	struct cmn2asic_msg_mapping msg_mapping;
431 	struct cmn2asic_mapping mapping;
432 
433 	switch (type) {
434 	case CMN2ASIC_MAPPING_MSG:
435 		if (index >= SMU_MSG_MAX_COUNT ||
436 		    !smu->message_map)
437 			return -EINVAL;
438 
439 		msg_mapping = smu->message_map[index];
440 		if (!msg_mapping.valid_mapping)
441 			return -EINVAL;
442 
443 		if (amdgpu_sriov_vf(smu->adev) &&
444 		    !msg_mapping.valid_in_vf)
445 			return -EACCES;
446 
447 		return msg_mapping.map_to;
448 
449 	case CMN2ASIC_MAPPING_CLK:
450 		if (index >= SMU_CLK_COUNT ||
451 		    !smu->clock_map)
452 			return -EINVAL;
453 
454 		mapping = smu->clock_map[index];
455 		if (!mapping.valid_mapping)
456 			return -EINVAL;
457 
458 		return mapping.map_to;
459 
460 	case CMN2ASIC_MAPPING_FEATURE:
461 		if (index >= SMU_FEATURE_COUNT ||
462 		    !smu->feature_map)
463 			return -EINVAL;
464 
465 		mapping = smu->feature_map[index];
466 		if (!mapping.valid_mapping)
467 			return -EINVAL;
468 
469 		return mapping.map_to;
470 
471 	case CMN2ASIC_MAPPING_TABLE:
472 		if (index >= SMU_TABLE_COUNT ||
473 		    !smu->table_map)
474 			return -EINVAL;
475 
476 		mapping = smu->table_map[index];
477 		if (!mapping.valid_mapping)
478 			return -EINVAL;
479 
480 		return mapping.map_to;
481 
482 	case CMN2ASIC_MAPPING_PWR:
483 		if (index >= SMU_POWER_SOURCE_COUNT ||
484 		    !smu->pwr_src_map)
485 			return -EINVAL;
486 
487 		mapping = smu->pwr_src_map[index];
488 		if (!mapping.valid_mapping)
489 			return -EINVAL;
490 
491 		return mapping.map_to;
492 
493 	case CMN2ASIC_MAPPING_WORKLOAD:
494 		if (index > PP_SMC_POWER_PROFILE_CUSTOM ||
495 		    !smu->workload_map)
496 			return -EINVAL;
497 
498 		mapping = smu->workload_map[index];
499 		if (!mapping.valid_mapping)
500 			return -EINVAL;
501 
502 		return mapping.map_to;
503 
504 	default:
505 		return -EINVAL;
506 	}
507 }
508 
509 int smu_cmn_feature_is_supported(struct smu_context *smu,
510 				 enum smu_feature_mask mask)
511 {
512 	struct smu_feature *feature = &smu->smu_feature;
513 	int feature_id;
514 
515 	feature_id = smu_cmn_to_asic_specific_index(smu,
516 						    CMN2ASIC_MAPPING_FEATURE,
517 						    mask);
518 	if (feature_id < 0)
519 		return 0;
520 
521 	WARN_ON(feature_id > feature->feature_num);
522 
523 	return test_bit(feature_id, feature->supported);
524 }
525 
526 int __smu_get_enabled_features(struct smu_context *smu,
527 			       uint64_t *enabled_features)
528 {
529 	return smu_cmn_call_asic_func(get_enabled_mask, smu, enabled_features);
530 }
531 
532 int smu_cmn_feature_is_enabled(struct smu_context *smu,
533 			       enum smu_feature_mask mask)
534 {
535 	struct amdgpu_device *adev = smu->adev;
536 	uint64_t enabled_features;
537 	int feature_id;
538 
539 	if (__smu_get_enabled_features(smu, &enabled_features)) {
540 		dev_err(adev->dev, "Failed to retrieve enabled ppfeatures!\n");
541 		return 0;
542 	}
543 
544 	/*
545 	 * For Renoir and Cyan Skillfish, they are assumed to have all features
546 	 * enabled. Also considering they have no feature_map available, the
547 	 * check here can avoid unwanted feature_map check below.
548 	 */
549 	if (enabled_features == ULLONG_MAX)
550 		return 1;
551 
552 	feature_id = smu_cmn_to_asic_specific_index(smu,
553 						    CMN2ASIC_MAPPING_FEATURE,
554 						    mask);
555 	if (feature_id < 0)
556 		return 0;
557 
558 	return test_bit(feature_id, (unsigned long *)&enabled_features);
559 }
560 
561 bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu,
562 				enum smu_clk_type clk_type)
563 {
564 	enum smu_feature_mask feature_id = 0;
565 
566 	switch (clk_type) {
567 	case SMU_MCLK:
568 	case SMU_UCLK:
569 		feature_id = SMU_FEATURE_DPM_UCLK_BIT;
570 		break;
571 	case SMU_GFXCLK:
572 	case SMU_SCLK:
573 		feature_id = SMU_FEATURE_DPM_GFXCLK_BIT;
574 		break;
575 	case SMU_SOCCLK:
576 		feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
577 		break;
578 	default:
579 		return true;
580 	}
581 
582 	if (!smu_cmn_feature_is_enabled(smu, feature_id))
583 		return false;
584 
585 	return true;
586 }
587 
588 int smu_cmn_get_enabled_mask(struct smu_context *smu,
589 			     uint64_t *feature_mask)
590 {
591 	uint32_t *feature_mask_high;
592 	uint32_t *feature_mask_low;
593 	int ret = 0, index = 0;
594 
595 	if (!feature_mask)
596 		return -EINVAL;
597 
598 	feature_mask_low = &((uint32_t *)feature_mask)[0];
599 	feature_mask_high = &((uint32_t *)feature_mask)[1];
600 
601 	index = smu_cmn_to_asic_specific_index(smu,
602 						CMN2ASIC_MAPPING_MSG,
603 						SMU_MSG_GetEnabledSmuFeatures);
604 	if (index > 0) {
605 		ret = smu_cmn_send_smc_msg_with_param(smu,
606 						      SMU_MSG_GetEnabledSmuFeatures,
607 						      0,
608 						      feature_mask_low);
609 		if (ret)
610 			return ret;
611 
612 		ret = smu_cmn_send_smc_msg_with_param(smu,
613 						      SMU_MSG_GetEnabledSmuFeatures,
614 						      1,
615 						      feature_mask_high);
616 	} else {
617 		ret = smu_cmn_send_smc_msg(smu,
618 					   SMU_MSG_GetEnabledSmuFeaturesHigh,
619 					   feature_mask_high);
620 		if (ret)
621 			return ret;
622 
623 		ret = smu_cmn_send_smc_msg(smu,
624 					   SMU_MSG_GetEnabledSmuFeaturesLow,
625 					   feature_mask_low);
626 	}
627 
628 	return ret;
629 }
630 
631 uint64_t smu_cmn_get_indep_throttler_status(
632 					const unsigned long dep_status,
633 					const uint8_t *throttler_map)
634 {
635 	uint64_t indep_status = 0;
636 	uint8_t dep_bit = 0;
637 
638 	for_each_set_bit(dep_bit, &dep_status, 32)
639 		indep_status |= 1ULL << throttler_map[dep_bit];
640 
641 	return indep_status;
642 }
643 
644 int smu_cmn_feature_update_enable_state(struct smu_context *smu,
645 					uint64_t feature_mask,
646 					bool enabled)
647 {
648 	int ret = 0;
649 
650 	if (enabled) {
651 		ret = smu_cmn_send_smc_msg_with_param(smu,
652 						  SMU_MSG_EnableSmuFeaturesLow,
653 						  lower_32_bits(feature_mask),
654 						  NULL);
655 		if (ret)
656 			return ret;
657 		ret = smu_cmn_send_smc_msg_with_param(smu,
658 						  SMU_MSG_EnableSmuFeaturesHigh,
659 						  upper_32_bits(feature_mask),
660 						  NULL);
661 	} else {
662 		ret = smu_cmn_send_smc_msg_with_param(smu,
663 						  SMU_MSG_DisableSmuFeaturesLow,
664 						  lower_32_bits(feature_mask),
665 						  NULL);
666 		if (ret)
667 			return ret;
668 		ret = smu_cmn_send_smc_msg_with_param(smu,
669 						  SMU_MSG_DisableSmuFeaturesHigh,
670 						  upper_32_bits(feature_mask),
671 						  NULL);
672 	}
673 
674 	return ret;
675 }
676 
677 int smu_cmn_feature_set_enabled(struct smu_context *smu,
678 				enum smu_feature_mask mask,
679 				bool enable)
680 {
681 	int feature_id;
682 
683 	feature_id = smu_cmn_to_asic_specific_index(smu,
684 						    CMN2ASIC_MAPPING_FEATURE,
685 						    mask);
686 	if (feature_id < 0)
687 		return -EINVAL;
688 
689 	return smu_cmn_feature_update_enable_state(smu,
690 					       1ULL << feature_id,
691 					       enable);
692 }
693 
694 #undef __SMU_DUMMY_MAP
695 #define __SMU_DUMMY_MAP(fea)	#fea
696 static const char* __smu_feature_names[] = {
697 	SMU_FEATURE_MASKS
698 };
699 
700 static const char *smu_get_feature_name(struct smu_context *smu,
701 					enum smu_feature_mask feature)
702 {
703 	if (feature < 0 || feature >= SMU_FEATURE_COUNT)
704 		return "unknown smu feature";
705 	return __smu_feature_names[feature];
706 }
707 
708 size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu,
709 				   char *buf)
710 {
711 	uint64_t feature_mask;
712 	int feature_index = 0;
713 	uint32_t count = 0;
714 	int8_t sort_feature[SMU_FEATURE_COUNT];
715 	size_t size = 0;
716 	int ret = 0, i;
717 	int feature_id;
718 
719 	ret = __smu_get_enabled_features(smu, &feature_mask);
720 	if (ret)
721 		return 0;
722 
723 	size =  sysfs_emit_at(buf, size, "features high: 0x%08x low: 0x%08x\n",
724 			upper_32_bits(feature_mask), lower_32_bits(feature_mask));
725 
726 	memset(sort_feature, -1, sizeof(sort_feature));
727 
728 	for (i = 0; i < SMU_FEATURE_COUNT; i++) {
729 		feature_index = smu_cmn_to_asic_specific_index(smu,
730 							       CMN2ASIC_MAPPING_FEATURE,
731 							       i);
732 		if (feature_index < 0)
733 			continue;
734 
735 		sort_feature[feature_index] = i;
736 	}
737 
738 	size += sysfs_emit_at(buf, size, "%-2s. %-20s  %-3s : %-s\n",
739 			"No", "Feature", "Bit", "State");
740 
741 	for (i = 0; i < SMU_FEATURE_COUNT; i++) {
742 		if (sort_feature[i] < 0)
743 			continue;
744 
745 		/* convert to asic spcific feature ID */
746 		feature_id = smu_cmn_to_asic_specific_index(smu,
747 							    CMN2ASIC_MAPPING_FEATURE,
748 							    sort_feature[i]);
749 		if (feature_id < 0)
750 			continue;
751 
752 		size += sysfs_emit_at(buf, size, "%02d. %-20s (%2d) : %s\n",
753 				count++,
754 				smu_get_feature_name(smu, sort_feature[i]),
755 				i,
756 				!!test_bit(feature_id, (unsigned long *)&feature_mask) ?
757 				"enabled" : "disabled");
758 	}
759 
760 	return size;
761 }
762 
763 int smu_cmn_set_pp_feature_mask(struct smu_context *smu,
764 				uint64_t new_mask)
765 {
766 	int ret = 0;
767 	uint64_t feature_mask;
768 	uint64_t feature_2_enabled = 0;
769 	uint64_t feature_2_disabled = 0;
770 
771 	ret = __smu_get_enabled_features(smu, &feature_mask);
772 	if (ret)
773 		return ret;
774 
775 	feature_2_enabled  = ~feature_mask & new_mask;
776 	feature_2_disabled = feature_mask & ~new_mask;
777 
778 	if (feature_2_enabled) {
779 		ret = smu_cmn_feature_update_enable_state(smu,
780 							  feature_2_enabled,
781 							  true);
782 		if (ret)
783 			return ret;
784 	}
785 	if (feature_2_disabled) {
786 		ret = smu_cmn_feature_update_enable_state(smu,
787 							  feature_2_disabled,
788 							  false);
789 		if (ret)
790 			return ret;
791 	}
792 
793 	return ret;
794 }
795 
796 /**
797  * smu_cmn_disable_all_features_with_exception - disable all dpm features
798  *                                               except this specified by
799  *                                               @mask
800  *
801  * @smu:               smu_context pointer
802  * @mask:              the dpm feature which should not be disabled
803  *                     SMU_FEATURE_COUNT: no exception, all dpm features
804  *                     to disable
805  *
806  * Returns:
807  * 0 on success or a negative error code on failure.
808  */
809 int smu_cmn_disable_all_features_with_exception(struct smu_context *smu,
810 						enum smu_feature_mask mask)
811 {
812 	uint64_t features_to_disable = U64_MAX;
813 	int skipped_feature_id;
814 
815 	if (mask != SMU_FEATURE_COUNT) {
816 		skipped_feature_id = smu_cmn_to_asic_specific_index(smu,
817 								    CMN2ASIC_MAPPING_FEATURE,
818 								    mask);
819 		if (skipped_feature_id < 0)
820 			return -EINVAL;
821 
822 		features_to_disable &= ~(1ULL << skipped_feature_id);
823 	}
824 
825 	return smu_cmn_feature_update_enable_state(smu,
826 						   features_to_disable,
827 						   0);
828 }
829 
830 int smu_cmn_get_smc_version(struct smu_context *smu,
831 			    uint32_t *if_version,
832 			    uint32_t *smu_version)
833 {
834 	int ret = 0;
835 
836 	if (!if_version && !smu_version)
837 		return -EINVAL;
838 
839 	if (smu->smc_fw_if_version && smu->smc_fw_version)
840 	{
841 		if (if_version)
842 			*if_version = smu->smc_fw_if_version;
843 
844 		if (smu_version)
845 			*smu_version = smu->smc_fw_version;
846 
847 		return 0;
848 	}
849 
850 	if (if_version) {
851 		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion, if_version);
852 		if (ret)
853 			return ret;
854 
855 		smu->smc_fw_if_version = *if_version;
856 	}
857 
858 	if (smu_version) {
859 		ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSmuVersion, smu_version);
860 		if (ret)
861 			return ret;
862 
863 		smu->smc_fw_version = *smu_version;
864 	}
865 
866 	return ret;
867 }
868 
869 int smu_cmn_update_table(struct smu_context *smu,
870 			 enum smu_table_id table_index,
871 			 int argument,
872 			 void *table_data,
873 			 bool drv2smu)
874 {
875 	struct smu_table_context *smu_table = &smu->smu_table;
876 	struct amdgpu_device *adev = smu->adev;
877 	struct smu_table *table = &smu_table->driver_table;
878 	int table_id = smu_cmn_to_asic_specific_index(smu,
879 						      CMN2ASIC_MAPPING_TABLE,
880 						      table_index);
881 	uint32_t table_size;
882 	int ret = 0;
883 	if (!table_data || table_id >= SMU_TABLE_COUNT || table_id < 0)
884 		return -EINVAL;
885 
886 	table_size = smu_table->tables[table_index].size;
887 
888 	if (drv2smu) {
889 		memcpy(table->cpu_addr, table_data, table_size);
890 		/*
891 		 * Flush hdp cache: to guard the content seen by
892 		 * GPU is consitent with CPU.
893 		 */
894 		amdgpu_asic_flush_hdp(adev, NULL);
895 	}
896 
897 	ret = smu_cmn_send_smc_msg_with_param(smu, drv2smu ?
898 					  SMU_MSG_TransferTableDram2Smu :
899 					  SMU_MSG_TransferTableSmu2Dram,
900 					  table_id | ((argument & 0xFFFF) << 16),
901 					  NULL);
902 	if (ret)
903 		return ret;
904 
905 	if (!drv2smu) {
906 		amdgpu_asic_invalidate_hdp(adev, NULL);
907 		memcpy(table_data, table->cpu_addr, table_size);
908 	}
909 
910 	return 0;
911 }
912 
913 int smu_cmn_write_watermarks_table(struct smu_context *smu)
914 {
915 	void *watermarks_table = smu->smu_table.watermarks_table;
916 
917 	if (!watermarks_table)
918 		return -EINVAL;
919 
920 	return smu_cmn_update_table(smu,
921 				    SMU_TABLE_WATERMARKS,
922 				    0,
923 				    watermarks_table,
924 				    true);
925 }
926 
927 int smu_cmn_write_pptable(struct smu_context *smu)
928 {
929 	void *pptable = smu->smu_table.driver_pptable;
930 
931 	return smu_cmn_update_table(smu,
932 				    SMU_TABLE_PPTABLE,
933 				    0,
934 				    pptable,
935 				    true);
936 }
937 
938 int smu_cmn_get_metrics_table(struct smu_context *smu,
939 			      void *metrics_table,
940 			      bool bypass_cache)
941 {
942 	struct smu_table_context *smu_table= &smu->smu_table;
943 	uint32_t table_size =
944 		smu_table->tables[SMU_TABLE_SMU_METRICS].size;
945 	int ret = 0;
946 
947 	if (bypass_cache ||
948 	    !smu_table->metrics_time ||
949 	    time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) {
950 		ret = smu_cmn_update_table(smu,
951 				       SMU_TABLE_SMU_METRICS,
952 				       0,
953 				       smu_table->metrics_table,
954 				       false);
955 		if (ret) {
956 			dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n");
957 			return ret;
958 		}
959 		smu_table->metrics_time = jiffies;
960 	}
961 
962 	if (metrics_table)
963 		memcpy(metrics_table, smu_table->metrics_table, table_size);
964 
965 	return 0;
966 }
967 
968 void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev)
969 {
970 	struct metrics_table_header *header = (struct metrics_table_header *)table;
971 	uint16_t structure_size;
972 
973 #define METRICS_VERSION(a, b)	((a << 16) | b )
974 
975 	switch (METRICS_VERSION(frev, crev)) {
976 	case METRICS_VERSION(1, 0):
977 		structure_size = sizeof(struct gpu_metrics_v1_0);
978 		break;
979 	case METRICS_VERSION(1, 1):
980 		structure_size = sizeof(struct gpu_metrics_v1_1);
981 		break;
982 	case METRICS_VERSION(1, 2):
983 		structure_size = sizeof(struct gpu_metrics_v1_2);
984 		break;
985 	case METRICS_VERSION(1, 3):
986 		structure_size = sizeof(struct gpu_metrics_v1_3);
987 		break;
988 	case METRICS_VERSION(2, 0):
989 		structure_size = sizeof(struct gpu_metrics_v2_0);
990 		break;
991 	case METRICS_VERSION(2, 1):
992 		structure_size = sizeof(struct gpu_metrics_v2_1);
993 		break;
994 	case METRICS_VERSION(2, 2):
995 		structure_size = sizeof(struct gpu_metrics_v2_2);
996 		break;
997 	default:
998 		return;
999 	}
1000 
1001 #undef METRICS_VERSION
1002 
1003 	memset(header, 0xFF, structure_size);
1004 
1005 	header->format_revision = frev;
1006 	header->content_revision = crev;
1007 	header->structure_size = structure_size;
1008 
1009 }
1010 
1011 int smu_cmn_set_mp1_state(struct smu_context *smu,
1012 			  enum pp_mp1_state mp1_state)
1013 {
1014 	enum smu_message_type msg;
1015 	int ret;
1016 
1017 	switch (mp1_state) {
1018 	case PP_MP1_STATE_SHUTDOWN:
1019 		msg = SMU_MSG_PrepareMp1ForShutdown;
1020 		break;
1021 	case PP_MP1_STATE_UNLOAD:
1022 		msg = SMU_MSG_PrepareMp1ForUnload;
1023 		break;
1024 	case PP_MP1_STATE_RESET:
1025 		msg = SMU_MSG_PrepareMp1ForReset;
1026 		break;
1027 	case PP_MP1_STATE_NONE:
1028 	default:
1029 		return 0;
1030 	}
1031 
1032 	ret = smu_cmn_send_smc_msg(smu, msg, NULL);
1033 	if (ret)
1034 		dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n");
1035 
1036 	return ret;
1037 }
1038 
1039 bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)
1040 {
1041 	struct pci_dev *p = NULL;
1042 	bool snd_driver_loaded;
1043 
1044 	/*
1045 	 * If the ASIC comes with no audio function, we always assume
1046 	 * it is "enabled".
1047 	 */
1048 	p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus),
1049 			adev->pdev->bus->number, 1);
1050 	if (!p)
1051 		return true;
1052 
1053 	snd_driver_loaded = pci_is_enabled(p) ? true : false;
1054 
1055 	pci_dev_put(p);
1056 
1057 	return snd_driver_loaded;
1058 }
1059