1 /* $NetBSD: amdgpu_smu9_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $ */
2
3 /*
4 * Copyright 2018 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_smu9_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $");
28
29 #include "smumgr.h"
30 #include "vega10_inc.h"
31 #include "soc15_common.h"
32 #include "pp_debug.h"
33
34
35 /* MP Apertures */
36 #define MP0_Public 0x03800000
37 #define MP0_SRAM 0x03900000
38 #define MP1_Public 0x03b00000
39 #define MP1_SRAM 0x03c00004
40
41 #define smnMP1_FIRMWARE_FLAGS 0x3010028
42
smu9_is_smc_ram_running(struct pp_hwmgr * hwmgr)43 bool smu9_is_smc_ram_running(struct pp_hwmgr *hwmgr)
44 {
45 struct amdgpu_device *adev = hwmgr->adev;
46 uint32_t mp1_fw_flags;
47
48 mp1_fw_flags = RREG32_PCIE(MP1_Public |
49 (smnMP1_FIRMWARE_FLAGS & 0xffffffff));
50
51 if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK)
52 return true;
53
54 return false;
55 }
56
57 /*
58 * Check if SMC has responded to previous message.
59 *
60 * @param smumgr the address of the powerplay hardware manager.
61 * @return TRUE SMC has responded, FALSE otherwise.
62 */
smu9_wait_for_response(struct pp_hwmgr * hwmgr)63 static uint32_t smu9_wait_for_response(struct pp_hwmgr *hwmgr)
64 {
65 struct amdgpu_device *adev = hwmgr->adev;
66 uint32_t reg;
67 uint32_t ret;
68
69 /* Due to the L1 policy problem under SRIOV, we have to use
70 * mmMP1_SMN_C2PMSG_103 as the driver response register
71 */
72 if (hwmgr->pp_one_vf) {
73 reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_103);
74
75 ret = phm_wait_for_register_unequal(hwmgr, reg,
76 0, MP1_C2PMSG_103__CONTENT_MASK);
77
78 if (ret)
79 pr_err("No response from smu\n");
80
81 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103);
82 } else {
83 reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
84
85 ret = phm_wait_for_register_unequal(hwmgr, reg,
86 0, MP1_C2PMSG_90__CONTENT_MASK);
87
88 if (ret)
89 pr_err("No response from smu\n");
90 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90);
91 }
92 }
93
94 /*
95 * Send a message to the SMC, and do not wait for its response.
96 * @param smumgr the address of the powerplay hardware manager.
97 * @param msg the message to send.
98 * @return Always return 0.
99 */
smu9_send_msg_to_smc_without_waiting(struct pp_hwmgr * hwmgr,uint16_t msg)100 static int smu9_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
101 uint16_t msg)
102 {
103 struct amdgpu_device *adev = hwmgr->adev;
104
105 if (hwmgr->pp_one_vf) {
106 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_101, msg);
107 } else {
108 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg);
109 }
110
111 return 0;
112 }
113
114 /*
115 * Send a message to the SMC, and wait for its response.
116 * @param hwmgr the address of the powerplay hardware manager.
117 * @param msg the message to send.
118 * @return Always return 0.
119 */
smu9_send_msg_to_smc(struct pp_hwmgr * hwmgr,uint16_t msg)120 int smu9_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
121 {
122 struct amdgpu_device *adev = hwmgr->adev;
123 uint32_t ret;
124
125 smu9_wait_for_response(hwmgr);
126
127 if (hwmgr->pp_one_vf)
128 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103, 0);
129 else
130 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
131
132 smu9_send_msg_to_smc_without_waiting(hwmgr, msg);
133
134 ret = smu9_wait_for_response(hwmgr);
135 if (ret != 1)
136 pr_err("Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret);
137
138 return 0;
139 }
140
141 /*
142 * Send a message to the SMC with parameter
143 * @param hwmgr: the address of the powerplay hardware manager.
144 * @param msg: the message to send.
145 * @param parameter: the parameter to send
146 * @return Always return 0.
147 */
smu9_send_msg_to_smc_with_parameter(struct pp_hwmgr * hwmgr,uint16_t msg,uint32_t parameter)148 int smu9_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
149 uint16_t msg, uint32_t parameter)
150 {
151 struct amdgpu_device *adev = hwmgr->adev;
152 uint32_t ret;
153
154 smu9_wait_for_response(hwmgr);
155
156 /* Due to the L1 policy problem under SRIOV, we have to use
157 * mmMP1_SMN_C2PMSG_101 as the driver message register and
158 * mmMP1_SMN_C2PMSG_102 as the driver parameter register.
159 */
160 if (hwmgr->pp_one_vf) {
161 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103, 0);
162 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_102, parameter);
163 } else {
164 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0);
165 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter);
166 }
167
168 smu9_send_msg_to_smc_without_waiting(hwmgr, msg);
169
170 ret = smu9_wait_for_response(hwmgr);
171 if (ret != 1)
172 pr_err("Failed message: 0x%x, input parameter: 0x%x, error code: 0x%x\n", msg, parameter, ret);
173
174 return 0;
175 }
176
smu9_get_argument(struct pp_hwmgr * hwmgr)177 uint32_t smu9_get_argument(struct pp_hwmgr *hwmgr)
178 {
179 struct amdgpu_device *adev = hwmgr->adev;
180
181 if (hwmgr->pp_one_vf)
182 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_102);
183 else
184 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82);
185 }
186