Line data Source code
1 : /*
2 : * Copyright 2018 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 _SMU_HELPER_H_
24 : #define _SMU_HELPER_H_
25 :
26 : struct pp_atomctrl_voltage_table;
27 : struct pp_hwmgr;
28 : struct phm_ppt_v1_voltage_lookup_table;
29 : struct Watermarks_t;
30 : struct pp_wm_sets_with_clock_ranges_soc15;
31 :
32 : uint8_t convert_to_vid(uint16_t vddc);
33 : uint16_t convert_to_vddc(uint8_t vid);
34 :
35 : struct watermark_row_generic_t {
36 : uint16_t MinClock;
37 : uint16_t MaxClock;
38 : uint16_t MinUclk;
39 : uint16_t MaxUclk;
40 :
41 : uint8_t WmSetting;
42 : uint8_t Padding[3];
43 : };
44 :
45 : struct watermarks {
46 : struct watermark_row_generic_t WatermarkRow[2][4];
47 : uint32_t padding[7];
48 : };
49 :
50 : int phm_copy_clock_limits_array(
51 : struct pp_hwmgr *hwmgr,
52 : uint32_t **pptable_info_array,
53 : const uint32_t *pptable_array,
54 : uint32_t power_saving_clock_count);
55 :
56 : int phm_copy_overdrive_settings_limits_array(
57 : struct pp_hwmgr *hwmgr,
58 : uint32_t **pptable_info_array,
59 : const uint32_t *pptable_array,
60 : uint32_t od_setting_count);
61 :
62 : extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr,
63 : uint32_t index,
64 : uint32_t value, uint32_t mask);
65 : extern int phm_wait_for_indirect_register_unequal(
66 : struct pp_hwmgr *hwmgr,
67 : uint32_t indirect_port, uint32_t index,
68 : uint32_t value, uint32_t mask);
69 :
70 :
71 : extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr);
72 : extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr);
73 : extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr);
74 :
75 : extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table);
76 : extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table);
77 : extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table);
78 : extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table);
79 : extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table);
80 : extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max);
81 : extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes);
82 : extern int32_t phm_get_dpm_level_enable_mask_value(void *table);
83 : extern uint8_t phm_get_voltage_id(struct pp_atomctrl_voltage_table *voltage_table,
84 : uint32_t voltage);
85 : extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage);
86 : extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci);
87 : extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level);
88 : extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table,
89 : uint16_t virtual_voltage_id, int32_t *sclk);
90 : extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
91 : extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask);
92 : extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr);
93 :
94 : extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
95 : uint32_t sclk, uint16_t id, uint16_t *voltage);
96 :
97 : extern uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size);
98 :
99 : extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
100 : uint32_t value, uint32_t mask);
101 :
102 : extern int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
103 : uint32_t indirect_port,
104 : uint32_t index,
105 : uint32_t value,
106 : uint32_t mask);
107 :
108 : int phm_irq_process(struct amdgpu_device *adev,
109 : struct amdgpu_irq_src *source,
110 : struct amdgpu_iv_entry *entry);
111 :
112 : /*
113 : * Helper function to make sysfs_emit_at() happy. Align buf to
114 : * the current page boundary and record the offset.
115 : */
116 : static inline void phm_get_sysfs_buf(char **buf, int *offset)
117 : {
118 0 : if (!*buf || !offset)
119 : return;
120 :
121 0 : *offset = offset_in_page(*buf);
122 0 : *buf -= *offset;
123 : }
124 :
125 : int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr);
126 :
127 : void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size,
128 : uint8_t *frev, uint8_t *crev);
129 :
130 : int smu_get_voltage_dependency_table_ppt_v1(
131 : const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table,
132 : struct phm_ppt_v1_clock_voltage_dependency_table *dep_table);
133 :
134 : int smu_set_watermarks_for_clocks_ranges(void *wt_table,
135 : struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges);
136 :
137 : #define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
138 : #define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK
139 :
140 : #define PHM_SET_FIELD(origval, reg, field, fieldval) \
141 : (((origval) & ~PHM_FIELD_MASK(reg, field)) | \
142 : (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field))))
143 :
144 : #define PHM_GET_FIELD(value, reg, field) \
145 : (((value) & PHM_FIELD_MASK(reg, field)) >> \
146 : PHM_FIELD_SHIFT(reg, field))
147 :
148 :
149 : /* Operations on named fields. */
150 :
151 : #define PHM_READ_FIELD(device, reg, field) \
152 : PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field)
153 :
154 : #define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \
155 : PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
156 : reg, field)
157 :
158 : #define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \
159 : PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
160 : reg, field)
161 :
162 : #define PHM_WRITE_FIELD(device, reg, field, fieldval) \
163 : cgs_write_register(device, mm##reg, PHM_SET_FIELD( \
164 : cgs_read_register(device, mm##reg), reg, field, fieldval))
165 :
166 : #define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \
167 : cgs_write_ind_register(device, port, ix##reg, \
168 : PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
169 : reg, field, fieldval))
170 :
171 : #define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \
172 : cgs_write_ind_register(device, port, ix##reg, \
173 : PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
174 : reg, field, fieldval))
175 :
176 : #define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \
177 : phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask)
178 :
179 :
180 : #define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \
181 : PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
182 :
183 : #define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \
184 : PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \
185 : << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
186 :
187 : #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \
188 : phm_wait_for_indirect_register_unequal(hwmgr, \
189 : mm##port##_INDEX, index, value, mask)
190 :
191 : #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \
192 : PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
193 :
194 : #define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \
195 : PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \
196 : (fieldval) << PHM_FIELD_SHIFT(reg, field), \
197 : PHM_FIELD_MASK(reg, field) )
198 :
199 :
200 : #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \
201 : port, index, value, mask) \
202 : phm_wait_for_indirect_register_unequal(hwmgr, \
203 : mm##port##_INDEX_11, index, value, mask)
204 :
205 : #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \
206 : PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
207 :
208 : #define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \
209 : PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \
210 : (fieldval) << PHM_FIELD_SHIFT(reg, field), \
211 : PHM_FIELD_MASK(reg, field))
212 :
213 :
214 : #define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, \
215 : port, index, value, mask) \
216 : phm_wait_on_indirect_register(hwmgr, \
217 : mm##port##_INDEX_11, index, value, mask)
218 :
219 : #define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \
220 : PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
221 :
222 : #define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \
223 : PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, \
224 : (fieldval) << PHM_FIELD_SHIFT(reg, field), \
225 : PHM_FIELD_MASK(reg, field))
226 :
227 : #define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \
228 : index, value, mask) \
229 : phm_wait_for_register_unequal(hwmgr, \
230 : index, value, mask)
231 :
232 : #define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \
233 : PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \
234 : mm##reg, value, mask)
235 :
236 : #define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \
237 : PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, \
238 : (fieldval) << PHM_FIELD_SHIFT(reg, field), \
239 : PHM_FIELD_MASK(reg, field))
240 :
241 : #endif /* _SMU_HELPER_H_ */
|