diff options
author | Maruthi Srinivas Bayyavarapu <Maruthi.Bayyavarapu@amd.com> | 2016-04-26 11:01:54 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-08-31 15:21:08 -0400 |
commit | 0c34f45368422dc34545a56a60f3884ffc3a4a3b (patch) | |
tree | 9fda77080946bddb137204da15104d426c81166e | |
parent | 9139d731fdaa52b85543f2713d65ca860e0ce884 (diff) |
drm/amdgpu: add SI SMC support
Signed-off-by: Maruthi Bayyavarapu <maruthi.bayyavarapu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/si_smc.c | 280 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/sislands_smc.h | 423 |
2 files changed, 703 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/si_smc.c b/drivers/gpu/drm/amd/amdgpu/si_smc.c new file mode 100644 index 000000000000..214f37c3b688 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/si_smc.c | |||
@@ -0,0 +1,280 @@ | |||
1 | /* | ||
2 | * Copyright 2011 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 | * Authors: Alex Deucher | ||
23 | */ | ||
24 | |||
25 | #include <linux/firmware.h> | ||
26 | #include "drmP.h" | ||
27 | #include "amdgpu.h" | ||
28 | #include "si/sid.h" | ||
29 | #include "ppsmc.h" | ||
30 | #include "amdgpu_ucode.h" | ||
31 | #include "sislands_smc.h" | ||
32 | |||
33 | static int si_set_smc_sram_address(struct amdgpu_device *adev, | ||
34 | u32 smc_address, u32 limit) | ||
35 | { | ||
36 | if (smc_address & 3) | ||
37 | return -EINVAL; | ||
38 | if ((smc_address + 3) > limit) | ||
39 | return -EINVAL; | ||
40 | |||
41 | WREG32(SMC_IND_INDEX_0, smc_address); | ||
42 | WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | int si_copy_bytes_to_smc(struct amdgpu_device *adev, | ||
48 | u32 smc_start_address, | ||
49 | const u8 *src, u32 byte_count, u32 limit) | ||
50 | { | ||
51 | unsigned long flags; | ||
52 | int ret = 0; | ||
53 | u32 data, original_data, addr, extra_shift; | ||
54 | |||
55 | if (smc_start_address & 3) | ||
56 | return -EINVAL; | ||
57 | if ((smc_start_address + byte_count) > limit) | ||
58 | return -EINVAL; | ||
59 | |||
60 | addr = smc_start_address; | ||
61 | |||
62 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | ||
63 | while (byte_count >= 4) { | ||
64 | /* SMC address space is BE */ | ||
65 | data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; | ||
66 | |||
67 | ret = si_set_smc_sram_address(adev, addr, limit); | ||
68 | if (ret) | ||
69 | goto done; | ||
70 | |||
71 | WREG32(SMC_IND_DATA_0, data); | ||
72 | |||
73 | src += 4; | ||
74 | byte_count -= 4; | ||
75 | addr += 4; | ||
76 | } | ||
77 | |||
78 | /* RMW for the final bytes */ | ||
79 | if (byte_count > 0) { | ||
80 | data = 0; | ||
81 | |||
82 | ret = si_set_smc_sram_address(adev, addr, limit); | ||
83 | if (ret) | ||
84 | goto done; | ||
85 | |||
86 | original_data = RREG32(SMC_IND_DATA_0); | ||
87 | |||
88 | extra_shift = 8 * (4 - byte_count); | ||
89 | |||
90 | while (byte_count > 0) { | ||
91 | /* SMC address space is BE */ | ||
92 | data = (data << 8) + *src++; | ||
93 | byte_count--; | ||
94 | } | ||
95 | |||
96 | data <<= extra_shift; | ||
97 | |||
98 | data |= (original_data & ~((~0UL) << extra_shift)); | ||
99 | |||
100 | ret = si_set_smc_sram_address(adev, addr, limit); | ||
101 | if (ret) | ||
102 | goto done; | ||
103 | |||
104 | WREG32(SMC_IND_DATA_0, data); | ||
105 | } | ||
106 | |||
107 | done: | ||
108 | spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | void si_start_smc(struct amdgpu_device *adev) | ||
114 | { | ||
115 | u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); | ||
116 | |||
117 | tmp &= ~RST_REG; | ||
118 | |||
119 | WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); | ||
120 | } | ||
121 | |||
122 | void si_reset_smc(struct amdgpu_device *adev) | ||
123 | { | ||
124 | u32 tmp; | ||
125 | |||
126 | RREG32(CB_CGTT_SCLK_CTRL); | ||
127 | RREG32(CB_CGTT_SCLK_CTRL); | ||
128 | RREG32(CB_CGTT_SCLK_CTRL); | ||
129 | RREG32(CB_CGTT_SCLK_CTRL); | ||
130 | |||
131 | tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); | ||
132 | tmp |= RST_REG; | ||
133 | WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); | ||
134 | } | ||
135 | |||
136 | int si_program_jump_on_start(struct amdgpu_device *adev) | ||
137 | { | ||
138 | static const u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; | ||
139 | |||
140 | return si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); | ||
141 | } | ||
142 | |||
143 | void si_stop_smc_clock(struct amdgpu_device *adev) | ||
144 | { | ||
145 | u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); | ||
146 | |||
147 | tmp |= CK_DISABLE; | ||
148 | |||
149 | WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); | ||
150 | } | ||
151 | |||
152 | void si_start_smc_clock(struct amdgpu_device *adev) | ||
153 | { | ||
154 | u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); | ||
155 | |||
156 | tmp &= ~CK_DISABLE; | ||
157 | |||
158 | WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); | ||
159 | } | ||
160 | |||
161 | bool si_is_smc_running(struct amdgpu_device *adev) | ||
162 | { | ||
163 | u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL); | ||
164 | u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); | ||
165 | |||
166 | if (!(rst & RST_REG) && !(clk & CK_DISABLE)) | ||
167 | return true; | ||
168 | |||
169 | return false; | ||
170 | } | ||
171 | |||
172 | PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg) | ||
173 | { | ||
174 | u32 tmp; | ||
175 | int i; | ||
176 | |||
177 | if (!si_is_smc_running(adev)) | ||
178 | return PPSMC_Result_Failed; | ||
179 | |||
180 | WREG32(SMC_MESSAGE_0, msg); | ||
181 | |||
182 | for (i = 0; i < adev->usec_timeout; i++) { | ||
183 | tmp = RREG32(SMC_RESP_0); | ||
184 | if (tmp != 0) | ||
185 | break; | ||
186 | udelay(1); | ||
187 | } | ||
188 | tmp = RREG32(SMC_RESP_0); | ||
189 | |||
190 | return (PPSMC_Result)tmp; | ||
191 | } | ||
192 | |||
193 | PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev) | ||
194 | { | ||
195 | u32 tmp; | ||
196 | int i; | ||
197 | |||
198 | if (!si_is_smc_running(adev)) | ||
199 | return PPSMC_Result_OK; | ||
200 | |||
201 | for (i = 0; i < adev->usec_timeout; i++) { | ||
202 | tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); | ||
203 | if ((tmp & CKEN) == 0) | ||
204 | break; | ||
205 | udelay(1); | ||
206 | } | ||
207 | |||
208 | return PPSMC_Result_OK; | ||
209 | } | ||
210 | |||
211 | int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) | ||
212 | { | ||
213 | const struct smc_firmware_header_v1_0 *hdr; | ||
214 | unsigned long flags; | ||
215 | u32 ucode_start_address; | ||
216 | u32 ucode_size; | ||
217 | const u8 *src; | ||
218 | u32 data; | ||
219 | |||
220 | if (!adev->pm.fw) | ||
221 | return -EINVAL; | ||
222 | |||
223 | hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data; | ||
224 | |||
225 | amdgpu_ucode_print_smc_hdr(&hdr->header); | ||
226 | |||
227 | ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); | ||
228 | ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); | ||
229 | src = (const u8 *) | ||
230 | (adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); | ||
231 | if (ucode_size & 3) | ||
232 | return -EINVAL; | ||
233 | |||
234 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | ||
235 | WREG32(SMC_IND_INDEX_0, ucode_start_address); | ||
236 | WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); | ||
237 | while (ucode_size >= 4) { | ||
238 | /* SMC address space is BE */ | ||
239 | data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; | ||
240 | |||
241 | WREG32(SMC_IND_DATA_0, data); | ||
242 | |||
243 | src += 4; | ||
244 | ucode_size -= 4; | ||
245 | } | ||
246 | WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); | ||
247 | spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | int si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, | ||
253 | u32 *value, u32 limit) | ||
254 | { | ||
255 | unsigned long flags; | ||
256 | int ret; | ||
257 | |||
258 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | ||
259 | ret = si_set_smc_sram_address(adev, smc_address, limit); | ||
260 | if (ret == 0) | ||
261 | *value = RREG32(SMC_IND_DATA_0); | ||
262 | spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | ||
263 | |||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | int si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, | ||
268 | u32 value, u32 limit) | ||
269 | { | ||
270 | unsigned long flags; | ||
271 | int ret; | ||
272 | |||
273 | spin_lock_irqsave(&adev->smc_idx_lock, flags); | ||
274 | ret = si_set_smc_sram_address(adev, smc_address, limit); | ||
275 | if (ret == 0) | ||
276 | WREG32(SMC_IND_DATA_0, value); | ||
277 | spin_unlock_irqrestore(&adev->smc_idx_lock, flags); | ||
278 | |||
279 | return ret; | ||
280 | } | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h new file mode 100644 index 000000000000..542ab46aeb40 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h | |||
@@ -0,0 +1,423 @@ | |||
1 | /* | ||
2 | * Copyright 2013 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 | #ifndef PP_SISLANDS_SMC_H | ||
24 | #define PP_SISLANDS_SMC_H | ||
25 | |||
26 | #include "ppsmc.h" | ||
27 | |||
28 | #pragma pack(push, 1) | ||
29 | |||
30 | #define SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 | ||
31 | |||
32 | struct PP_SIslands_Dpm2PerfLevel | ||
33 | { | ||
34 | uint8_t MaxPS; | ||
35 | uint8_t TgtAct; | ||
36 | uint8_t MaxPS_StepInc; | ||
37 | uint8_t MaxPS_StepDec; | ||
38 | uint8_t PSSamplingTime; | ||
39 | uint8_t NearTDPDec; | ||
40 | uint8_t AboveSafeInc; | ||
41 | uint8_t BelowSafeInc; | ||
42 | uint8_t PSDeltaLimit; | ||
43 | uint8_t PSDeltaWin; | ||
44 | uint16_t PwrEfficiencyRatio; | ||
45 | uint8_t Reserved[4]; | ||
46 | }; | ||
47 | |||
48 | typedef struct PP_SIslands_Dpm2PerfLevel PP_SIslands_Dpm2PerfLevel; | ||
49 | |||
50 | struct PP_SIslands_DPM2Status | ||
51 | { | ||
52 | uint32_t dpm2Flags; | ||
53 | uint8_t CurrPSkip; | ||
54 | uint8_t CurrPSkipPowerShift; | ||
55 | uint8_t CurrPSkipTDP; | ||
56 | uint8_t CurrPSkipOCP; | ||
57 | uint8_t MaxSPLLIndex; | ||
58 | uint8_t MinSPLLIndex; | ||
59 | uint8_t CurrSPLLIndex; | ||
60 | uint8_t InfSweepMode; | ||
61 | uint8_t InfSweepDir; | ||
62 | uint8_t TDPexceeded; | ||
63 | uint8_t reserved; | ||
64 | uint8_t SwitchDownThreshold; | ||
65 | uint32_t SwitchDownCounter; | ||
66 | uint32_t SysScalingFactor; | ||
67 | }; | ||
68 | |||
69 | typedef struct PP_SIslands_DPM2Status PP_SIslands_DPM2Status; | ||
70 | |||
71 | struct PP_SIslands_DPM2Parameters | ||
72 | { | ||
73 | uint32_t TDPLimit; | ||
74 | uint32_t NearTDPLimit; | ||
75 | uint32_t SafePowerLimit; | ||
76 | uint32_t PowerBoostLimit; | ||
77 | uint32_t MinLimitDelta; | ||
78 | }; | ||
79 | typedef struct PP_SIslands_DPM2Parameters PP_SIslands_DPM2Parameters; | ||
80 | |||
81 | struct PP_SIslands_PAPMStatus | ||
82 | { | ||
83 | uint32_t EstimatedDGPU_T; | ||
84 | uint32_t EstimatedDGPU_P; | ||
85 | uint32_t EstimatedAPU_T; | ||
86 | uint32_t EstimatedAPU_P; | ||
87 | uint8_t dGPU_T_Limit_Exceeded; | ||
88 | uint8_t reserved[3]; | ||
89 | }; | ||
90 | typedef struct PP_SIslands_PAPMStatus PP_SIslands_PAPMStatus; | ||
91 | |||
92 | struct PP_SIslands_PAPMParameters | ||
93 | { | ||
94 | uint32_t NearTDPLimitTherm; | ||
95 | uint32_t NearTDPLimitPAPM; | ||
96 | uint32_t PlatformPowerLimit; | ||
97 | uint32_t dGPU_T_Limit; | ||
98 | uint32_t dGPU_T_Warning; | ||
99 | uint32_t dGPU_T_Hysteresis; | ||
100 | }; | ||
101 | typedef struct PP_SIslands_PAPMParameters PP_SIslands_PAPMParameters; | ||
102 | |||
103 | struct SISLANDS_SMC_SCLK_VALUE | ||
104 | { | ||
105 | uint32_t vCG_SPLL_FUNC_CNTL; | ||
106 | uint32_t vCG_SPLL_FUNC_CNTL_2; | ||
107 | uint32_t vCG_SPLL_FUNC_CNTL_3; | ||
108 | uint32_t vCG_SPLL_FUNC_CNTL_4; | ||
109 | uint32_t vCG_SPLL_SPREAD_SPECTRUM; | ||
110 | uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; | ||
111 | uint32_t sclk_value; | ||
112 | }; | ||
113 | |||
114 | typedef struct SISLANDS_SMC_SCLK_VALUE SISLANDS_SMC_SCLK_VALUE; | ||
115 | |||
116 | struct SISLANDS_SMC_MCLK_VALUE | ||
117 | { | ||
118 | uint32_t vMPLL_FUNC_CNTL; | ||
119 | uint32_t vMPLL_FUNC_CNTL_1; | ||
120 | uint32_t vMPLL_FUNC_CNTL_2; | ||
121 | uint32_t vMPLL_AD_FUNC_CNTL; | ||
122 | uint32_t vMPLL_DQ_FUNC_CNTL; | ||
123 | uint32_t vMCLK_PWRMGT_CNTL; | ||
124 | uint32_t vDLL_CNTL; | ||
125 | uint32_t vMPLL_SS; | ||
126 | uint32_t vMPLL_SS2; | ||
127 | uint32_t mclk_value; | ||
128 | }; | ||
129 | |||
130 | typedef struct SISLANDS_SMC_MCLK_VALUE SISLANDS_SMC_MCLK_VALUE; | ||
131 | |||
132 | struct SISLANDS_SMC_VOLTAGE_VALUE | ||
133 | { | ||
134 | uint16_t value; | ||
135 | uint8_t index; | ||
136 | uint8_t phase_settings; | ||
137 | }; | ||
138 | |||
139 | typedef struct SISLANDS_SMC_VOLTAGE_VALUE SISLANDS_SMC_VOLTAGE_VALUE; | ||
140 | |||
141 | struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL | ||
142 | { | ||
143 | uint8_t ACIndex; | ||
144 | uint8_t displayWatermark; | ||
145 | uint8_t gen2PCIE; | ||
146 | uint8_t UVDWatermark; | ||
147 | uint8_t VCEWatermark; | ||
148 | uint8_t strobeMode; | ||
149 | uint8_t mcFlags; | ||
150 | uint8_t padding; | ||
151 | uint32_t aT; | ||
152 | uint32_t bSP; | ||
153 | SISLANDS_SMC_SCLK_VALUE sclk; | ||
154 | SISLANDS_SMC_MCLK_VALUE mclk; | ||
155 | SISLANDS_SMC_VOLTAGE_VALUE vddc; | ||
156 | SISLANDS_SMC_VOLTAGE_VALUE mvdd; | ||
157 | SISLANDS_SMC_VOLTAGE_VALUE vddci; | ||
158 | SISLANDS_SMC_VOLTAGE_VALUE std_vddc; | ||
159 | uint8_t hysteresisUp; | ||
160 | uint8_t hysteresisDown; | ||
161 | uint8_t stateFlags; | ||
162 | uint8_t arbRefreshState; | ||
163 | uint32_t SQPowerThrottle; | ||
164 | uint32_t SQPowerThrottle_2; | ||
165 | uint32_t MaxPoweredUpCU; | ||
166 | SISLANDS_SMC_VOLTAGE_VALUE high_temp_vddc; | ||
167 | SISLANDS_SMC_VOLTAGE_VALUE low_temp_vddc; | ||
168 | uint32_t reserved[2]; | ||
169 | PP_SIslands_Dpm2PerfLevel dpm2; | ||
170 | }; | ||
171 | |||
172 | #define SISLANDS_SMC_STROBE_RATIO 0x0F | ||
173 | #define SISLANDS_SMC_STROBE_ENABLE 0x10 | ||
174 | |||
175 | #define SISLANDS_SMC_MC_EDC_RD_FLAG 0x01 | ||
176 | #define SISLANDS_SMC_MC_EDC_WR_FLAG 0x02 | ||
177 | #define SISLANDS_SMC_MC_RTT_ENABLE 0x04 | ||
178 | #define SISLANDS_SMC_MC_STUTTER_EN 0x08 | ||
179 | #define SISLANDS_SMC_MC_PG_EN 0x10 | ||
180 | |||
181 | typedef struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL SISLANDS_SMC_HW_PERFORMANCE_LEVEL; | ||
182 | |||
183 | struct SISLANDS_SMC_SWSTATE | ||
184 | { | ||
185 | uint8_t flags; | ||
186 | uint8_t levelCount; | ||
187 | uint8_t padding2; | ||
188 | uint8_t padding3; | ||
189 | SISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1]; | ||
190 | }; | ||
191 | |||
192 | typedef struct SISLANDS_SMC_SWSTATE SISLANDS_SMC_SWSTATE; | ||
193 | |||
194 | #define SISLANDS_SMC_VOLTAGEMASK_VDDC 0 | ||
195 | #define SISLANDS_SMC_VOLTAGEMASK_MVDD 1 | ||
196 | #define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2 | ||
197 | #define SISLANDS_SMC_VOLTAGEMASK_MAX 4 | ||
198 | |||
199 | struct SISLANDS_SMC_VOLTAGEMASKTABLE | ||
200 | { | ||
201 | uint32_t lowMask[SISLANDS_SMC_VOLTAGEMASK_MAX]; | ||
202 | }; | ||
203 | |||
204 | typedef struct SISLANDS_SMC_VOLTAGEMASKTABLE SISLANDS_SMC_VOLTAGEMASKTABLE; | ||
205 | |||
206 | #define SISLANDS_MAX_NO_VREG_STEPS 32 | ||
207 | |||
208 | struct SISLANDS_SMC_STATETABLE | ||
209 | { | ||
210 | uint8_t thermalProtectType; | ||
211 | uint8_t systemFlags; | ||
212 | uint8_t maxVDDCIndexInPPTable; | ||
213 | uint8_t extraFlags; | ||
214 | uint32_t lowSMIO[SISLANDS_MAX_NO_VREG_STEPS]; | ||
215 | SISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable; | ||
216 | SISLANDS_SMC_VOLTAGEMASKTABLE phaseMaskTable; | ||
217 | PP_SIslands_DPM2Parameters dpm2Params; | ||
218 | SISLANDS_SMC_SWSTATE initialState; | ||
219 | SISLANDS_SMC_SWSTATE ACPIState; | ||
220 | SISLANDS_SMC_SWSTATE ULVState; | ||
221 | SISLANDS_SMC_SWSTATE driverState; | ||
222 | SISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1]; | ||
223 | }; | ||
224 | |||
225 | typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE; | ||
226 | |||
227 | #define SI_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0 | ||
228 | #define SI_SMC_SOFT_REGISTER_delay_vreg 0xC | ||
229 | #define SI_SMC_SOFT_REGISTER_delay_acpi 0x28 | ||
230 | #define SI_SMC_SOFT_REGISTER_seq_index 0x5C | ||
231 | #define SI_SMC_SOFT_REGISTER_mvdd_chg_time 0x60 | ||
232 | #define SI_SMC_SOFT_REGISTER_mclk_switch_lim 0x70 | ||
233 | #define SI_SMC_SOFT_REGISTER_watermark_threshold 0x78 | ||
234 | #define SI_SMC_SOFT_REGISTER_phase_shedding_delay 0x88 | ||
235 | #define SI_SMC_SOFT_REGISTER_ulv_volt_change_delay 0x8C | ||
236 | #define SI_SMC_SOFT_REGISTER_mc_block_delay 0x98 | ||
237 | #define SI_SMC_SOFT_REGISTER_ticks_per_us 0xA8 | ||
238 | #define SI_SMC_SOFT_REGISTER_crtc_index 0xC4 | ||
239 | #define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min 0xC8 | ||
240 | #define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max 0xCC | ||
241 | #define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4 | ||
242 | #define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC | ||
243 | #define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100 | ||
244 | #define SI_SMC_SOFT_REGISTER_svi_rework_plat_type 0x118 | ||
245 | #define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c | ||
246 | #define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120 | ||
247 | |||
248 | struct PP_SIslands_FanTable | ||
249 | { | ||
250 | uint8_t fdo_mode; | ||
251 | uint8_t padding; | ||
252 | int16_t temp_min; | ||
253 | int16_t temp_med; | ||
254 | int16_t temp_max; | ||
255 | int16_t slope1; | ||
256 | int16_t slope2; | ||
257 | int16_t fdo_min; | ||
258 | int16_t hys_up; | ||
259 | int16_t hys_down; | ||
260 | int16_t hys_slope; | ||
261 | int16_t temp_resp_lim; | ||
262 | int16_t temp_curr; | ||
263 | int16_t slope_curr; | ||
264 | int16_t pwm_curr; | ||
265 | uint32_t refresh_period; | ||
266 | int16_t fdo_max; | ||
267 | uint8_t temp_src; | ||
268 | int8_t padding2; | ||
269 | }; | ||
270 | |||
271 | typedef struct PP_SIslands_FanTable PP_SIslands_FanTable; | ||
272 | |||
273 | #define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 | ||
274 | #define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32 | ||
275 | |||
276 | #define SMC_SISLANDS_SCALE_I 7 | ||
277 | #define SMC_SISLANDS_SCALE_R 12 | ||
278 | |||
279 | struct PP_SIslands_CacConfig | ||
280 | { | ||
281 | uint16_t cac_lkge_lut[SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES]; | ||
282 | uint32_t lkge_lut_V0; | ||
283 | uint32_t lkge_lut_Vstep; | ||
284 | uint32_t WinTime; | ||
285 | uint32_t R_LL; | ||
286 | uint32_t calculation_repeats; | ||
287 | uint32_t l2numWin_TDP; | ||
288 | uint32_t dc_cac; | ||
289 | uint8_t lts_truncate_n; | ||
290 | uint8_t SHIFT_N; | ||
291 | uint8_t log2_PG_LKG_SCALE; | ||
292 | uint8_t cac_temp; | ||
293 | uint32_t lkge_lut_T0; | ||
294 | uint32_t lkge_lut_Tstep; | ||
295 | }; | ||
296 | |||
297 | typedef struct PP_SIslands_CacConfig PP_SIslands_CacConfig; | ||
298 | |||
299 | #define SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE 16 | ||
300 | #define SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20 | ||
301 | |||
302 | struct SMC_SIslands_MCRegisterAddress | ||
303 | { | ||
304 | uint16_t s0; | ||
305 | uint16_t s1; | ||
306 | }; | ||
307 | |||
308 | typedef struct SMC_SIslands_MCRegisterAddress SMC_SIslands_MCRegisterAddress; | ||
309 | |||
310 | struct SMC_SIslands_MCRegisterSet | ||
311 | { | ||
312 | uint32_t value[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; | ||
313 | }; | ||
314 | |||
315 | typedef struct SMC_SIslands_MCRegisterSet SMC_SIslands_MCRegisterSet; | ||
316 | |||
317 | struct SMC_SIslands_MCRegisters | ||
318 | { | ||
319 | uint8_t last; | ||
320 | uint8_t reserved[3]; | ||
321 | SMC_SIslands_MCRegisterAddress address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; | ||
322 | SMC_SIslands_MCRegisterSet data[SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT]; | ||
323 | }; | ||
324 | |||
325 | typedef struct SMC_SIslands_MCRegisters SMC_SIslands_MCRegisters; | ||
326 | |||
327 | struct SMC_SIslands_MCArbDramTimingRegisterSet | ||
328 | { | ||
329 | uint32_t mc_arb_dram_timing; | ||
330 | uint32_t mc_arb_dram_timing2; | ||
331 | uint8_t mc_arb_rfsh_rate; | ||
332 | uint8_t mc_arb_burst_time; | ||
333 | uint8_t padding[2]; | ||
334 | }; | ||
335 | |||
336 | typedef struct SMC_SIslands_MCArbDramTimingRegisterSet SMC_SIslands_MCArbDramTimingRegisterSet; | ||
337 | |||
338 | struct SMC_SIslands_MCArbDramTimingRegisters | ||
339 | { | ||
340 | uint8_t arb_current; | ||
341 | uint8_t reserved[3]; | ||
342 | SMC_SIslands_MCArbDramTimingRegisterSet data[16]; | ||
343 | }; | ||
344 | |||
345 | typedef struct SMC_SIslands_MCArbDramTimingRegisters SMC_SIslands_MCArbDramTimingRegisters; | ||
346 | |||
347 | struct SMC_SISLANDS_SPLL_DIV_TABLE | ||
348 | { | ||
349 | uint32_t freq[256]; | ||
350 | uint32_t ss[256]; | ||
351 | }; | ||
352 | |||
353 | #define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK 0x01ffffff | ||
354 | #define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT 0 | ||
355 | #define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK 0xfe000000 | ||
356 | #define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT 25 | ||
357 | #define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK 0x000fffff | ||
358 | #define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT 0 | ||
359 | #define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK 0xfff00000 | ||
360 | #define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT 20 | ||
361 | |||
362 | typedef struct SMC_SISLANDS_SPLL_DIV_TABLE SMC_SISLANDS_SPLL_DIV_TABLE; | ||
363 | |||
364 | #define SMC_SISLANDS_DTE_MAX_FILTER_STAGES 5 | ||
365 | |||
366 | #define SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE 16 | ||
367 | |||
368 | struct Smc_SIslands_DTE_Configuration | ||
369 | { | ||
370 | uint32_t tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; | ||
371 | uint32_t R[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; | ||
372 | uint32_t K; | ||
373 | uint32_t T0; | ||
374 | uint32_t MaxT; | ||
375 | uint8_t WindowSize; | ||
376 | uint8_t Tdep_count; | ||
377 | uint8_t temp_select; | ||
378 | uint8_t DTE_mode; | ||
379 | uint8_t T_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; | ||
380 | uint32_t Tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; | ||
381 | uint32_t Tdep_R[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; | ||
382 | uint32_t Tthreshold; | ||
383 | }; | ||
384 | |||
385 | typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration; | ||
386 | |||
387 | #define SMC_SISLANDS_DTE_STATUS_FLAG_DTE_ON 1 | ||
388 | |||
389 | #define SISLANDS_SMC_FIRMWARE_HEADER_LOCATION 0x10000 | ||
390 | |||
391 | #define SISLANDS_SMC_FIRMWARE_HEADER_version 0x0 | ||
392 | #define SISLANDS_SMC_FIRMWARE_HEADER_flags 0x4 | ||
393 | #define SISLANDS_SMC_FIRMWARE_HEADER_softRegisters 0xC | ||
394 | #define SISLANDS_SMC_FIRMWARE_HEADER_stateTable 0x10 | ||
395 | #define SISLANDS_SMC_FIRMWARE_HEADER_fanTable 0x14 | ||
396 | #define SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable 0x18 | ||
397 | #define SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable 0x24 | ||
398 | #define SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable 0x30 | ||
399 | #define SISLANDS_SMC_FIRMWARE_HEADER_spllTable 0x38 | ||
400 | #define SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration 0x40 | ||
401 | #define SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters 0x48 | ||
402 | |||
403 | #pragma pack(pop) | ||
404 | |||
405 | int si_copy_bytes_to_smc(struct amdgpu_device *adev, | ||
406 | u32 smc_start_address, | ||
407 | const u8 *src, u32 byte_count, u32 limit); | ||
408 | void si_start_smc(struct amdgpu_device *adev); | ||
409 | void si_reset_smc(struct amdgpu_device *adev); | ||
410 | int si_program_jump_on_start(struct amdgpu_device *adev); | ||
411 | void si_stop_smc_clock(struct amdgpu_device *adev); | ||
412 | void si_start_smc_clock(struct amdgpu_device *adev); | ||
413 | bool si_is_smc_running(struct amdgpu_device *adev); | ||
414 | PPSMC_Result si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg); | ||
415 | PPSMC_Result si_wait_for_smc_inactive(struct amdgpu_device *adev); | ||
416 | int si_load_smc_ucode(struct amdgpu_device *adev, u32 limit); | ||
417 | int si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, | ||
418 | u32 *value, u32 limit); | ||
419 | int si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, | ||
420 | u32 value, u32 limit); | ||
421 | |||
422 | #endif | ||
423 | |||