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
24#include <linux/math64.h>
25#include <linux/pci.h>
26#include <linux/seq_file.h>
27
28#include "atom.h"
29#include "evergreen.h"
30#include "r600_dpm.h"
31#include "rv770.h"
32#include "radeon.h"
33#include "radeon_asic.h"
34#include "ni_dpm.h"
35#include "si_dpm.h"
36#include "si.h"
37#include "sid.h"
38#include "vce.h"
39
40#define MC_CG_ARB_FREQ_F0           0x0a
41#define MC_CG_ARB_FREQ_F1           0x0b
42#define MC_CG_ARB_FREQ_F2           0x0c
43#define MC_CG_ARB_FREQ_F3           0x0d
44
45#define SMC_RAM_END                 0x20000
46
47#define SCLK_MIN_DEEPSLEEP_FREQ     1350
48
49static const struct si_cac_config_reg cac_weights_tahiti[] = {
50	{ 0x0, 0x0000ffff, 0, 0xc, SISLANDS_CACCONFIG_CGIND },
51	{ 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
52	{ 0x1, 0x0000ffff, 0, 0x101, SISLANDS_CACCONFIG_CGIND },
53	{ 0x1, 0xffff0000, 16, 0xc, SISLANDS_CACCONFIG_CGIND },
54	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
55	{ 0x3, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
56	{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
57	{ 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
58	{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
59	{ 0x5, 0x0000ffff, 0, 0x8fc, SISLANDS_CACCONFIG_CGIND },
60	{ 0x5, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
61	{ 0x6, 0x0000ffff, 0, 0x95, SISLANDS_CACCONFIG_CGIND },
62	{ 0x6, 0xffff0000, 16, 0x34e, SISLANDS_CACCONFIG_CGIND },
63	{ 0x18f, 0x0000ffff, 0, 0x1a1, SISLANDS_CACCONFIG_CGIND },
64	{ 0x7, 0x0000ffff, 0, 0xda, SISLANDS_CACCONFIG_CGIND },
65	{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
66	{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
67	{ 0x8, 0xffff0000, 16, 0x46, SISLANDS_CACCONFIG_CGIND },
68	{ 0x9, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
69	{ 0xa, 0x0000ffff, 0, 0x208, SISLANDS_CACCONFIG_CGIND },
70	{ 0xb, 0x0000ffff, 0, 0xe7, SISLANDS_CACCONFIG_CGIND },
71	{ 0xb, 0xffff0000, 16, 0x948, SISLANDS_CACCONFIG_CGIND },
72	{ 0xc, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
73	{ 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
74	{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
75	{ 0xe, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
76	{ 0xf, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
77	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
78	{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
79	{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
80	{ 0x11, 0x0000ffff, 0, 0x167, SISLANDS_CACCONFIG_CGIND },
81	{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
82	{ 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
83	{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
84	{ 0x13, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
85	{ 0x14, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
86	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
87	{ 0x15, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
88	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
89	{ 0x16, 0x0000ffff, 0, 0x31, SISLANDS_CACCONFIG_CGIND },
90	{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
91	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
92	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
93	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
94	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
95	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
96	{ 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
97	{ 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
98	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
99	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
100	{ 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
101	{ 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
102	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
103	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
104	{ 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
105	{ 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
106	{ 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
107	{ 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
108	{ 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
109	{ 0x6d, 0x0000ffff, 0, 0x18e, SISLANDS_CACCONFIG_CGIND },
110	{ 0xFFFFFFFF }
111};
112
113static const struct si_cac_config_reg lcac_tahiti[] = {
114	{ 0x143, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
115	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
116	{ 0x146, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
117	{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
118	{ 0x149, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
119	{ 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
120	{ 0x14c, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND },
121	{ 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
122	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
123	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
124	{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
125	{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
126	{ 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
127	{ 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
128	{ 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
129	{ 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
130	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
131	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
132	{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
133	{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
134	{ 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
135	{ 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
136	{ 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
137	{ 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
138	{ 0x8c, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
139	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
140	{ 0x8f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
141	{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
142	{ 0x92, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
143	{ 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
144	{ 0x95, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
145	{ 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
146	{ 0x14f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
147	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
148	{ 0x152, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
149	{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
150	{ 0x155, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
151	{ 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
152	{ 0x158, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
153	{ 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
154	{ 0x110, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
155	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
156	{ 0x113, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
157	{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
158	{ 0x116, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
159	{ 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
160	{ 0x119, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND },
161	{ 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
162	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
163	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
164	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
165	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
166	{ 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
167	{ 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
168	{ 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
169	{ 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
170	{ 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
171	{ 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
172	{ 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
173	{ 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
174	{ 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
175	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
176	{ 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
177	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
178	{ 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
179	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
180	{ 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
181	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
182	{ 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
183	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
184	{ 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
185	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
186	{ 0x16d, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
187	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
188	{ 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
189	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
190	{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
191	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
192	{ 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
193	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
194	{ 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
195	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
196	{ 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
197	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
198	{ 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
199	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
200	{ 0xFFFFFFFF }
201
202};
203
204static const struct si_cac_config_reg cac_override_tahiti[] = {
205	{ 0xFFFFFFFF }
206};
207
208static const struct si_powertune_data powertune_data_tahiti = {
209	((1 << 16) | 27027),
210	6,
211	0,
212	4,
213	95,
214	{
215		0UL,
216		0UL,
217		4521550UL,
218		309631529UL,
219		-1270850L,
220		4513710L,
221		40
222	},
223	595000000UL,
224	12,
225	{
226		0,
227		0,
228		0,
229		0,
230		0,
231		0,
232		0,
233		0
234	},
235	true
236};
237
238static const struct si_dte_data dte_data_tahiti = {
239	{ 1159409, 0, 0, 0, 0 },
240	{ 777, 0, 0, 0, 0 },
241	2,
242	54000,
243	127000,
244	25,
245	2,
246	10,
247	13,
248	{ 27, 31, 35, 39, 43, 47, 54, 61, 67, 74, 81, 88, 95, 0, 0, 0 },
249	{ 240888759, 221057860, 235370597, 162287531, 158510299, 131423027, 116673180, 103067515, 87941937, 76209048, 68209175, 64090048, 58301890, 0, 0, 0 },
250	{ 12024, 11189, 11451, 8411, 7939, 6666, 5681, 4905, 4241, 3720, 3354, 3122, 2890, 0, 0, 0 },
251	85,
252	false
253};
254
255static const struct si_dte_data dte_data_tahiti_pro = {
256	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
257	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
258	5,
259	45000,
260	100,
261	0xA,
262	1,
263	0,
264	0x10,
265	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
266	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
267	{ 0x7D0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
268	90,
269	true
270};
271
272static const struct si_dte_data dte_data_new_zealand = {
273	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0 },
274	{ 0x29B, 0x3E9, 0x537, 0x7D2, 0 },
275	0x5,
276	0xAFC8,
277	0x69,
278	0x32,
279	1,
280	0,
281	0x10,
282	{ 0x82, 0xA0, 0xB4, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
283	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
284	{ 0xDAC, 0x1388, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685 },
285	85,
286	true
287};
288
289static const struct si_dte_data dte_data_aruba_pro = {
290	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
291	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
292	5,
293	45000,
294	100,
295	0xA,
296	1,
297	0,
298	0x10,
299	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
300	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
301	{ 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
302	90,
303	true
304};
305
306static const struct si_dte_data dte_data_malta = {
307	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
308	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
309	5,
310	45000,
311	100,
312	0xA,
313	1,
314	0,
315	0x10,
316	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
317	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
318	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
319	90,
320	true
321};
322
323static struct si_cac_config_reg cac_weights_pitcairn[] = {
324	{ 0x0, 0x0000ffff, 0, 0x8a, SISLANDS_CACCONFIG_CGIND },
325	{ 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
326	{ 0x1, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
327	{ 0x1, 0xffff0000, 16, 0x24d, SISLANDS_CACCONFIG_CGIND },
328	{ 0x2, 0x0000ffff, 0, 0x19, SISLANDS_CACCONFIG_CGIND },
329	{ 0x3, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
330	{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
331	{ 0x4, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
332	{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
333	{ 0x5, 0x0000ffff, 0, 0xc11, SISLANDS_CACCONFIG_CGIND },
334	{ 0x5, 0xffff0000, 16, 0x7f3, SISLANDS_CACCONFIG_CGIND },
335	{ 0x6, 0x0000ffff, 0, 0x403, SISLANDS_CACCONFIG_CGIND },
336	{ 0x6, 0xffff0000, 16, 0x367, SISLANDS_CACCONFIG_CGIND },
337	{ 0x18f, 0x0000ffff, 0, 0x4c9, SISLANDS_CACCONFIG_CGIND },
338	{ 0x7, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
339	{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
340	{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
341	{ 0x8, 0xffff0000, 16, 0x45d, SISLANDS_CACCONFIG_CGIND },
342	{ 0x9, 0x0000ffff, 0, 0x36d, SISLANDS_CACCONFIG_CGIND },
343	{ 0xa, 0x0000ffff, 0, 0x534, SISLANDS_CACCONFIG_CGIND },
344	{ 0xb, 0x0000ffff, 0, 0x5da, SISLANDS_CACCONFIG_CGIND },
345	{ 0xb, 0xffff0000, 16, 0x880, SISLANDS_CACCONFIG_CGIND },
346	{ 0xc, 0x0000ffff, 0, 0x201, SISLANDS_CACCONFIG_CGIND },
347	{ 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
348	{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
349	{ 0xe, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND },
350	{ 0xf, 0x0000ffff, 0, 0x1f, SISLANDS_CACCONFIG_CGIND },
351	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
352	{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
353	{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
354	{ 0x11, 0x0000ffff, 0, 0x5de, SISLANDS_CACCONFIG_CGIND },
355	{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
356	{ 0x12, 0x0000ffff, 0, 0x7b, SISLANDS_CACCONFIG_CGIND },
357	{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
358	{ 0x13, 0xffff0000, 16, 0x13, SISLANDS_CACCONFIG_CGIND },
359	{ 0x14, 0x0000ffff, 0, 0xf9, SISLANDS_CACCONFIG_CGIND },
360	{ 0x15, 0x0000ffff, 0, 0x66, SISLANDS_CACCONFIG_CGIND },
361	{ 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
362	{ 0x4e, 0x0000ffff, 0, 0x13, SISLANDS_CACCONFIG_CGIND },
363	{ 0x16, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
364	{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
365	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
366	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
367	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
368	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
369	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
370	{ 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
371	{ 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
372	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
373	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
374	{ 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
375	{ 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
376	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
377	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
378	{ 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
379	{ 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
380	{ 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
381	{ 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
382	{ 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
383	{ 0x6d, 0x0000ffff, 0, 0x186, SISLANDS_CACCONFIG_CGIND },
384	{ 0xFFFFFFFF }
385};
386
387static const struct si_cac_config_reg lcac_pitcairn[] = {
388	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
389	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
390	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
391	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
392	{ 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
393	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
394	{ 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
395	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
396	{ 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
397	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
398	{ 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
399	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
400	{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
401	{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
402	{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
403	{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
404	{ 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
405	{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
406	{ 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
407	{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
408	{ 0x8f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
409	{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
410	{ 0x146, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
411	{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
412	{ 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
413	{ 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
414	{ 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
415	{ 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
416	{ 0x116, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
417	{ 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
418	{ 0x155, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
419	{ 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
420	{ 0x92, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
421	{ 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
422	{ 0x149, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
423	{ 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
424	{ 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
425	{ 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
426	{ 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
427	{ 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
428	{ 0x119, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
429	{ 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
430	{ 0x158, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
431	{ 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
432	{ 0x95, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
433	{ 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
434	{ 0x14c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
435	{ 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
436	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
437	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
438	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
439	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
440	{ 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
441	{ 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
442	{ 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
443	{ 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
444	{ 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
445	{ 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
446	{ 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
447	{ 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
448	{ 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
449	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
450	{ 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
451	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
452	{ 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
453	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
454	{ 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
455	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
456	{ 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
457	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
458	{ 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
459	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
460	{ 0x16d, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
461	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
462	{ 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
463	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
464	{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
465	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
466	{ 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
467	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
468	{ 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
469	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
470	{ 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
471	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
472	{ 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
473	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
474	{ 0xFFFFFFFF }
475};
476
477static const struct si_cac_config_reg cac_override_pitcairn[] = {
478	{ 0xFFFFFFFF }
479};
480
481static const struct si_powertune_data powertune_data_pitcairn = {
482	((1 << 16) | 27027),
483	5,
484	0,
485	6,
486	100,
487	{
488		51600000UL,
489		1800000UL,
490		7194395UL,
491		309631529UL,
492		-1270850L,
493		4513710L,
494		100
495	},
496	117830498UL,
497	12,
498	{
499		0,
500		0,
501		0,
502		0,
503		0,
504		0,
505		0,
506		0
507	},
508	true
509};
510
511static const struct si_dte_data dte_data_pitcairn = {
512	{ 0, 0, 0, 0, 0 },
513	{ 0, 0, 0, 0, 0 },
514	0,
515	0,
516	0,
517	0,
518	0,
519	0,
520	0,
521	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
522	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
523	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
524	0,
525	false
526};
527
528static const struct si_dte_data dte_data_curacao_xt = {
529	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
530	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
531	5,
532	45000,
533	100,
534	0xA,
535	1,
536	0,
537	0x10,
538	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
539	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
540	{ 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
541	90,
542	true
543};
544
545static const struct si_dte_data dte_data_curacao_pro = {
546	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
547	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
548	5,
549	45000,
550	100,
551	0xA,
552	1,
553	0,
554	0x10,
555	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
556	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
557	{ 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
558	90,
559	true
560};
561
562static const struct si_dte_data dte_data_neptune_xt = {
563	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
564	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
565	5,
566	45000,
567	100,
568	0xA,
569	1,
570	0,
571	0x10,
572	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
573	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
574	{ 0x3A2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
575	90,
576	true
577};
578
579static const struct si_cac_config_reg cac_weights_chelsea_pro[] = {
580	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
581	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
582	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
583	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
584	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
585	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
586	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
587	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
588	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
589	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
590	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
591	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
592	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
593	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
594	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
595	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
596	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
597	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
598	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
599	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
600	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
601	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
602	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
603	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
604	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
605	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
606	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
607	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
608	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
609	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
610	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
611	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
612	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
613	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
614	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
615	{ 0x14, 0x0000ffff, 0, 0x2BD, SISLANDS_CACCONFIG_CGIND },
616	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
617	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
618	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
619	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
620	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
621	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
622	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
623	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
624	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
625	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
626	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
627	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
628	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
629	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
630	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
631	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
632	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
633	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
634	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
635	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
636	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
637	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
638	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
639	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
640	{ 0xFFFFFFFF }
641};
642
643static const struct si_cac_config_reg cac_weights_chelsea_xt[] = {
644	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
645	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
646	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
647	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
648	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
649	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
650	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
651	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
652	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
653	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
654	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
655	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
656	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
657	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
658	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
659	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
660	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
661	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
662	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
663	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
664	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
665	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
666	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
667	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
668	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
669	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
670	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
671	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
672	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
673	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
674	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
675	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
676	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
677	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
678	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
679	{ 0x14, 0x0000ffff, 0, 0x30A, SISLANDS_CACCONFIG_CGIND },
680	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
681	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
682	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
683	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
684	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
685	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
686	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
687	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
688	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
689	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
690	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
691	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
692	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
693	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
694	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
695	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
696	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
697	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
698	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
699	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
700	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
701	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
702	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
703	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
704	{ 0xFFFFFFFF }
705};
706
707static const struct si_cac_config_reg cac_weights_heathrow[] = {
708	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
709	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
710	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
711	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
712	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
713	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
714	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
715	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
716	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
717	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
718	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
719	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
720	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
721	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
722	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
723	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
724	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
725	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
726	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
727	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
728	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
729	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
730	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
731	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
732	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
733	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
734	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
735	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
736	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
737	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
738	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
739	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
740	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
741	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
742	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
743	{ 0x14, 0x0000ffff, 0, 0x362, SISLANDS_CACCONFIG_CGIND },
744	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
745	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
746	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
747	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
748	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
749	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
750	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
751	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
752	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
753	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
754	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
755	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
756	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
757	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
758	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
759	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
760	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
761	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
762	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
763	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
764	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
765	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
766	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
767	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
768	{ 0xFFFFFFFF }
769};
770
771static const struct si_cac_config_reg cac_weights_cape_verde_pro[] = {
772	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
773	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
774	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
775	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
776	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
777	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
778	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
779	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
780	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
781	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
782	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
783	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
784	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
785	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
786	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
787	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
788	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
789	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
790	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
791	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
792	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
793	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
794	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
795	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
796	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
797	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
798	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
799	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
800	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
801	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
802	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
803	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
804	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
805	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
806	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
807	{ 0x14, 0x0000ffff, 0, 0x315, SISLANDS_CACCONFIG_CGIND },
808	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
809	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
810	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
811	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
812	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
813	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
814	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
815	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
816	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
817	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
818	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
819	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
820	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
821	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
822	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
823	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
824	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
825	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
826	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
827	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
828	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
829	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
830	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
831	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
832	{ 0xFFFFFFFF }
833};
834
835static const struct si_cac_config_reg cac_weights_cape_verde[] = {
836	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
837	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
838	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
839	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
840	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
841	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
842	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
843	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
844	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
845	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
846	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
847	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
848	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
849	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
850	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
851	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
852	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
853	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
854	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
855	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
856	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
857	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
858	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
859	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
860	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
861	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
862	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
863	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
864	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
865	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
866	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
867	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
868	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
869	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
870	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
871	{ 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND },
872	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
873	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
874	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
875	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
876	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
877	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
878	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
879	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
880	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
881	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
882	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
883	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
884	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
885	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
886	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
887	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
888	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
889	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
890	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
891	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
892	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
893	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
894	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
895	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
896	{ 0xFFFFFFFF }
897};
898
899static const struct si_cac_config_reg lcac_cape_verde[] = {
900	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
901	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
902	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
903	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
904	{ 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
905	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
906	{ 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
907	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
908	{ 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
909	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
910	{ 0x143, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
911	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
912	{ 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
913	{ 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
914	{ 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
915	{ 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
916	{ 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
917	{ 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
918	{ 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND },
919	{ 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
920	{ 0x8f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
921	{ 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
922	{ 0x146, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
923	{ 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
924	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
925	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
926	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
927	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
928	{ 0x164, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
929	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
930	{ 0x167, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
931	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
932	{ 0x16a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
933	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
934	{ 0x15e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
935	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
936	{ 0x161, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
937	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
938	{ 0x15b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
939	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
940	{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
941	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
942	{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
943	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
944	{ 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
945	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
946	{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
947	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
948	{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
949	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
950	{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
951	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
952	{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
953	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
954	{ 0xFFFFFFFF }
955};
956
957static const struct si_cac_config_reg cac_override_cape_verde[] = {
958	{ 0xFFFFFFFF }
959};
960
961static const struct si_powertune_data powertune_data_cape_verde = {
962	((1 << 16) | 0x6993),
963	5,
964	0,
965	7,
966	105,
967	{
968		0UL,
969		0UL,
970		7194395UL,
971		309631529UL,
972		-1270850L,
973		4513710L,
974		100
975	},
976	117830498UL,
977	12,
978	{
979		0,
980		0,
981		0,
982		0,
983		0,
984		0,
985		0,
986		0
987	},
988	true
989};
990
991static const struct si_dte_data dte_data_cape_verde = {
992	{ 0, 0, 0, 0, 0 },
993	{ 0, 0, 0, 0, 0 },
994	0,
995	0,
996	0,
997	0,
998	0,
999	0,
1000	0,
1001	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1002	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1003	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1004	0,
1005	false
1006};
1007
1008static const struct si_dte_data dte_data_venus_xtx = {
1009	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
1010	{ 0x71C, 0xAAB, 0xE39, 0x11C7, 0x0 },
1011	5,
1012	55000,
1013	0x69,
1014	0xA,
1015	1,
1016	0,
1017	0x3,
1018	{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1019	{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1020	{ 0xD6D8, 0x88B8, 0x1555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1021	90,
1022	true
1023};
1024
1025static const struct si_dte_data dte_data_venus_xt = {
1026	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
1027	{ 0xBDA, 0x11C7, 0x17B4, 0x1DA1, 0x0 },
1028	5,
1029	55000,
1030	0x69,
1031	0xA,
1032	1,
1033	0,
1034	0x3,
1035	{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1036	{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1037	{ 0xAFC8, 0x88B8, 0x238E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1038	90,
1039	true
1040};
1041
1042static const struct si_dte_data dte_data_venus_pro = {
1043	{  0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
1044	{ 0x11C7, 0x1AAB, 0x238E, 0x2C72, 0x0 },
1045	5,
1046	55000,
1047	0x69,
1048	0xA,
1049	1,
1050	0,
1051	0x3,
1052	{ 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1053	{ 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1054	{ 0x88B8, 0x88B8, 0x3555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1055	90,
1056	true
1057};
1058
1059static struct si_cac_config_reg cac_weights_oland[] = {
1060	{ 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND },
1061	{ 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
1062	{ 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND },
1063	{ 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND },
1064	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1065	{ 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
1066	{ 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND },
1067	{ 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND },
1068	{ 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND },
1069	{ 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND },
1070	{ 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND },
1071	{ 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND },
1072	{ 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND },
1073	{ 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
1074	{ 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND },
1075	{ 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND },
1076	{ 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND },
1077	{ 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND },
1078	{ 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND },
1079	{ 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND },
1080	{ 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND },
1081	{ 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND },
1082	{ 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND },
1083	{ 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND },
1084	{ 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND },
1085	{ 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
1086	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
1087	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1088	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1089	{ 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND },
1090	{ 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
1091	{ 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND },
1092	{ 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND },
1093	{ 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND },
1094	{ 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
1095	{ 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND },
1096	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1097	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
1098	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1099	{ 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND },
1100	{ 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND },
1101	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1102	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1103	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1104	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1105	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1106	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1107	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1108	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1109	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1110	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1111	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1112	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1113	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1114	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1115	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1116	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1117	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1118	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1119	{ 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND },
1120	{ 0xFFFFFFFF }
1121};
1122
1123static const struct si_cac_config_reg cac_weights_mars_pro[] = {
1124	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
1125	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1126	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
1127	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
1128	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1129	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1130	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1131	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1132	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
1133	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
1134	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
1135	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
1136	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
1137	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
1138	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
1139	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
1140	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
1141	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
1142	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
1143	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
1144	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
1145	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
1146	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
1147	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
1148	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
1149	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
1150	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
1151	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
1152	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1153	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
1154	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
1155	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1156	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
1157	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
1158	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
1159	{ 0x14, 0x0000ffff, 0, 0x2, SISLANDS_CACCONFIG_CGIND },
1160	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1161	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
1162	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1163	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
1164	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
1165	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1166	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1167	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1168	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1169	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1170	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
1171	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1172	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1173	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1174	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
1175	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
1176	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1177	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1178	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1179	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1180	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1181	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1182	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1183	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
1184	{ 0xFFFFFFFF }
1185};
1186
1187static const struct si_cac_config_reg cac_weights_mars_xt[] = {
1188	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
1189	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1190	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
1191	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
1192	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1193	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1194	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1195	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1196	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
1197	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
1198	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
1199	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
1200	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
1201	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
1202	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
1203	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
1204	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
1205	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
1206	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
1207	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
1208	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
1209	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
1210	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
1211	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
1212	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
1213	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
1214	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
1215	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
1216	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1217	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
1218	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
1219	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1220	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
1221	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
1222	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
1223	{ 0x14, 0x0000ffff, 0, 0x60, SISLANDS_CACCONFIG_CGIND },
1224	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1225	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
1226	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1227	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
1228	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
1229	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1230	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1231	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1232	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1233	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1234	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
1235	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1236	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1237	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1238	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
1239	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
1240	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1241	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1242	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1243	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1244	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1245	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1246	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1247	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
1248	{ 0xFFFFFFFF }
1249};
1250
1251static const struct si_cac_config_reg cac_weights_oland_pro[] = {
1252	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
1253	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1254	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
1255	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
1256	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1257	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1258	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1259	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1260	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
1261	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
1262	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
1263	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
1264	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
1265	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
1266	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
1267	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
1268	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
1269	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
1270	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
1271	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
1272	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
1273	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
1274	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
1275	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
1276	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
1277	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
1278	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
1279	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
1280	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1281	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
1282	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
1283	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1284	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
1285	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
1286	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
1287	{ 0x14, 0x0000ffff, 0, 0x90, SISLANDS_CACCONFIG_CGIND },
1288	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1289	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
1290	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1291	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
1292	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
1293	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1294	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1295	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1296	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1297	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1298	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
1299	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1300	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1301	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1302	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
1303	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
1304	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1305	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1306	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1307	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1308	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1309	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1310	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1311	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
1312	{ 0xFFFFFFFF }
1313};
1314
1315static const struct si_cac_config_reg cac_weights_oland_xt[] = {
1316	{ 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND },
1317	{ 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1318	{ 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND },
1319	{ 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND },
1320	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1321	{ 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1322	{ 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND },
1323	{ 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND },
1324	{ 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND },
1325	{ 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND },
1326	{ 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND },
1327	{ 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND },
1328	{ 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND },
1329	{ 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND },
1330	{ 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND },
1331	{ 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND },
1332	{ 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND },
1333	{ 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND },
1334	{ 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND },
1335	{ 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND },
1336	{ 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND },
1337	{ 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND },
1338	{ 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND },
1339	{ 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND },
1340	{ 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND },
1341	{ 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND },
1342	{ 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND },
1343	{ 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND },
1344	{ 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1345	{ 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND },
1346	{ 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND },
1347	{ 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1348	{ 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND },
1349	{ 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND },
1350	{ 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND },
1351	{ 0x14, 0x0000ffff, 0, 0x120, SISLANDS_CACCONFIG_CGIND },
1352	{ 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1353	{ 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND },
1354	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1355	{ 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND },
1356	{ 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND },
1357	{ 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1358	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1359	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1360	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1361	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1362	{ 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND },
1363	{ 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND },
1364	{ 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1365	{ 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1366	{ 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND },
1367	{ 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND },
1368	{ 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1369	{ 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1370	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1371	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1372	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1373	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1374	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1375	{ 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND },
1376	{ 0xFFFFFFFF }
1377};
1378
1379static const struct si_cac_config_reg lcac_oland[] = {
1380	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1381	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1382	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1383	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1384	{ 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
1385	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1386	{ 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
1387	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1388	{ 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
1389	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1390	{ 0x143, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND },
1391	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1392	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1393	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1394	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1395	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1396	{ 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1397	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1398	{ 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1399	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1400	{ 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1401	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1402	{ 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1403	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1404	{ 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1405	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1406	{ 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1407	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1408	{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1409	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1410	{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1411	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1412	{ 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1413	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1414	{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1415	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1416	{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1417	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1418	{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1419	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1420	{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1421	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1422	{ 0xFFFFFFFF }
1423};
1424
1425static const struct si_cac_config_reg lcac_mars_pro[] = {
1426	{ 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1427	{ 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1428	{ 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1429	{ 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1430	{ 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
1431	{ 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1432	{ 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
1433	{ 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1434	{ 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND },
1435	{ 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1436	{ 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1437	{ 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1438	{ 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1439	{ 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1440	{ 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1441	{ 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1442	{ 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1443	{ 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1444	{ 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1445	{ 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1446	{ 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1447	{ 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1448	{ 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1449	{ 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1450	{ 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1451	{ 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1452	{ 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1453	{ 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1454	{ 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND },
1455	{ 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1456	{ 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1457	{ 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1458	{ 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1459	{ 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1460	{ 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1461	{ 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1462	{ 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1463	{ 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1464	{ 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1465	{ 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1466	{ 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND },
1467	{ 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND },
1468	{ 0xFFFFFFFF }
1469};
1470
1471static const struct si_cac_config_reg cac_override_oland[] = {
1472	{ 0xFFFFFFFF }
1473};
1474
1475static const struct si_powertune_data powertune_data_oland = {
1476	((1 << 16) | 0x6993),
1477	5,
1478	0,
1479	7,
1480	105,
1481	{
1482		0UL,
1483		0UL,
1484		7194395UL,
1485		309631529UL,
1486		-1270850L,
1487		4513710L,
1488		100
1489	},
1490	117830498UL,
1491	12,
1492	{
1493		0,
1494		0,
1495		0,
1496		0,
1497		0,
1498		0,
1499		0,
1500		0
1501	},
1502	true
1503};
1504
1505static const struct si_powertune_data powertune_data_mars_pro = {
1506	((1 << 16) | 0x6993),
1507	5,
1508	0,
1509	7,
1510	105,
1511	{
1512		0UL,
1513		0UL,
1514		7194395UL,
1515		309631529UL,
1516		-1270850L,
1517		4513710L,
1518		100
1519	},
1520	117830498UL,
1521	12,
1522	{
1523		0,
1524		0,
1525		0,
1526		0,
1527		0,
1528		0,
1529		0,
1530		0
1531	},
1532	true
1533};
1534
1535static const struct si_dte_data dte_data_oland = {
1536	{ 0, 0, 0, 0, 0 },
1537	{ 0, 0, 0, 0, 0 },
1538	0,
1539	0,
1540	0,
1541	0,
1542	0,
1543	0,
1544	0,
1545	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1546	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1547	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1548	0,
1549	false
1550};
1551
1552static const struct si_dte_data dte_data_mars_pro = {
1553	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
1554	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
1555	5,
1556	55000,
1557	105,
1558	0xA,
1559	1,
1560	0,
1561	0x10,
1562	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
1563	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
1564	{ 0xF627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1565	90,
1566	true
1567};
1568
1569static const struct si_dte_data dte_data_sun_xt = {
1570	{ 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 },
1571	{ 0x0, 0x0, 0x0, 0x0, 0x0 },
1572	5,
1573	55000,
1574	105,
1575	0xA,
1576	1,
1577	0,
1578	0x10,
1579	{ 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
1580	{ 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 },
1581	{ 0xD555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
1582	90,
1583	true
1584};
1585
1586
1587static const struct si_cac_config_reg cac_weights_hainan[] = {
1588	{ 0x0, 0x0000ffff, 0, 0x2d9, SISLANDS_CACCONFIG_CGIND },
1589	{ 0x0, 0xffff0000, 16, 0x22b, SISLANDS_CACCONFIG_CGIND },
1590	{ 0x1, 0x0000ffff, 0, 0x21c, SISLANDS_CACCONFIG_CGIND },
1591	{ 0x1, 0xffff0000, 16, 0x1dc, SISLANDS_CACCONFIG_CGIND },
1592	{ 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1593	{ 0x3, 0x0000ffff, 0, 0x24e, SISLANDS_CACCONFIG_CGIND },
1594	{ 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1595	{ 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1596	{ 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1597	{ 0x5, 0x0000ffff, 0, 0x35e, SISLANDS_CACCONFIG_CGIND },
1598	{ 0x5, 0xffff0000, 16, 0x1143, SISLANDS_CACCONFIG_CGIND },
1599	{ 0x6, 0x0000ffff, 0, 0xe17, SISLANDS_CACCONFIG_CGIND },
1600	{ 0x6, 0xffff0000, 16, 0x441, SISLANDS_CACCONFIG_CGIND },
1601	{ 0x18f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1602	{ 0x7, 0x0000ffff, 0, 0x28b, SISLANDS_CACCONFIG_CGIND },
1603	{ 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1604	{ 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1605	{ 0x8, 0xffff0000, 16, 0xabe, SISLANDS_CACCONFIG_CGIND },
1606	{ 0x9, 0x0000ffff, 0, 0xf11, SISLANDS_CACCONFIG_CGIND },
1607	{ 0xa, 0x0000ffff, 0, 0x907, SISLANDS_CACCONFIG_CGIND },
1608	{ 0xb, 0x0000ffff, 0, 0xb45, SISLANDS_CACCONFIG_CGIND },
1609	{ 0xb, 0xffff0000, 16, 0xd1e, SISLANDS_CACCONFIG_CGIND },
1610	{ 0xc, 0x0000ffff, 0, 0xa2c, SISLANDS_CACCONFIG_CGIND },
1611	{ 0xd, 0x0000ffff, 0, 0x62, SISLANDS_CACCONFIG_CGIND },
1612	{ 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1613	{ 0xe, 0x0000ffff, 0, 0x1f3, SISLANDS_CACCONFIG_CGIND },
1614	{ 0xf, 0x0000ffff, 0, 0x42, SISLANDS_CACCONFIG_CGIND },
1615	{ 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1616	{ 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1617	{ 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1618	{ 0x11, 0x0000ffff, 0, 0x709, SISLANDS_CACCONFIG_CGIND },
1619	{ 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1620	{ 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1621	{ 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1622	{ 0x13, 0xffff0000, 16, 0x3a, SISLANDS_CACCONFIG_CGIND },
1623	{ 0x14, 0x0000ffff, 0, 0x357, SISLANDS_CACCONFIG_CGIND },
1624	{ 0x15, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND },
1625	{ 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1626	{ 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1627	{ 0x16, 0x0000ffff, 0, 0x314, SISLANDS_CACCONFIG_CGIND },
1628	{ 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1629	{ 0x17, 0x0000ffff, 0, 0x6d, SISLANDS_CACCONFIG_CGIND },
1630	{ 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1631	{ 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1632	{ 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND },
1633	{ 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND },
1634	{ 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1635	{ 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1636	{ 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1637	{ 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1638	{ 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1639	{ 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1640	{ 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1641	{ 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1642	{ 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1643	{ 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1644	{ 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1645	{ 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND },
1646	{ 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND },
1647	{ 0x6d, 0x0000ffff, 0, 0x1b9, SISLANDS_CACCONFIG_CGIND },
1648	{ 0xFFFFFFFF }
1649};
1650
1651static const struct si_powertune_data powertune_data_hainan = {
1652	((1 << 16) | 0x6993),
1653	5,
1654	0,
1655	9,
1656	105,
1657	{
1658		0UL,
1659		0UL,
1660		7194395UL,
1661		309631529UL,
1662		-1270850L,
1663		4513710L,
1664		100
1665	},
1666	117830498UL,
1667	12,
1668	{
1669		0,
1670		0,
1671		0,
1672		0,
1673		0,
1674		0,
1675		0,
1676		0
1677	},
1678	true
1679};
1680
1681static int si_populate_voltage_value(struct radeon_device *rdev,
1682				     const struct atom_voltage_table *table,
1683				     u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage);
1684static int si_get_std_voltage_value(struct radeon_device *rdev,
1685				    SISLANDS_SMC_VOLTAGE_VALUE *voltage,
1686				    u16 *std_voltage);
1687static int si_write_smc_soft_register(struct radeon_device *rdev,
1688				      u16 reg_offset, u32 value);
1689static int si_convert_power_level_to_smc(struct radeon_device *rdev,
1690					 struct rv7xx_pl *pl,
1691					 SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level);
1692static int si_calculate_sclk_params(struct radeon_device *rdev,
1693				    u32 engine_clock,
1694				    SISLANDS_SMC_SCLK_VALUE *sclk);
1695
1696static void si_thermal_start_smc_fan_control(struct radeon_device *rdev);
1697static void si_fan_ctrl_set_default_mode(struct radeon_device *rdev);
1698
1699static struct si_power_info *si_get_pi(struct radeon_device *rdev)
1700{
1701	struct si_power_info *pi = rdev->pm.dpm.priv;
1702
1703	return pi;
1704}
1705
1706static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff,
1707						     u16 v, s32 t, u32 ileakage, u32 *leakage)
1708{
1709	s64 kt, kv, leakage_w, i_leakage, vddc;
1710	s64 temperature, t_slope, t_intercept, av, bv, t_ref;
1711	s64 tmp;
1712
1713	i_leakage = div64_s64(drm_int2fixp(ileakage), 100);
1714	vddc = div64_s64(drm_int2fixp(v), 1000);
1715	temperature = div64_s64(drm_int2fixp(t), 1000);
1716
1717	t_slope = div64_s64(drm_int2fixp(coeff->t_slope), 100000000);
1718	t_intercept = div64_s64(drm_int2fixp(coeff->t_intercept), 100000000);
1719	av = div64_s64(drm_int2fixp(coeff->av), 100000000);
1720	bv = div64_s64(drm_int2fixp(coeff->bv), 100000000);
1721	t_ref = drm_int2fixp(coeff->t_ref);
1722
1723	tmp = drm_fixp_mul(t_slope, vddc) + t_intercept;
1724	kt = drm_fixp_exp(drm_fixp_mul(tmp, temperature));
1725	kt = drm_fixp_div(kt, drm_fixp_exp(drm_fixp_mul(tmp, t_ref)));
1726	kv = drm_fixp_mul(av, drm_fixp_exp(drm_fixp_mul(bv, vddc)));
1727
1728	leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);
1729
1730	*leakage = drm_fixp2int(leakage_w * 1000);
1731}
1732
1733static void si_calculate_leakage_for_v_and_t(struct radeon_device *rdev,
1734					     const struct ni_leakage_coeffients *coeff,
1735					     u16 v,
1736					     s32 t,
1737					     u32 i_leakage,
1738					     u32 *leakage)
1739{
1740	si_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);
1741}
1742
1743static void si_calculate_leakage_for_v_formula(const struct ni_leakage_coeffients *coeff,
1744					       const u32 fixed_kt, u16 v,
1745					       u32 ileakage, u32 *leakage)
1746{
1747	s64 kt, kv, leakage_w, i_leakage, vddc;
1748
1749	i_leakage = div64_s64(drm_int2fixp(ileakage), 100);
1750	vddc = div64_s64(drm_int2fixp(v), 1000);
1751
1752	kt = div64_s64(drm_int2fixp(fixed_kt), 100000000);
1753	kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 100000000),
1754			  drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 100000000), vddc)));
1755
1756	leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);
1757
1758	*leakage = drm_fixp2int(leakage_w * 1000);
1759}
1760
1761static void si_calculate_leakage_for_v(struct radeon_device *rdev,
1762				       const struct ni_leakage_coeffients *coeff,
1763				       const u32 fixed_kt,
1764				       u16 v,
1765				       u32 i_leakage,
1766				       u32 *leakage)
1767{
1768	si_calculate_leakage_for_v_formula(coeff, fixed_kt, v, i_leakage, leakage);
1769}
1770
1771
1772static void si_update_dte_from_pl2(struct radeon_device *rdev,
1773				   struct si_dte_data *dte_data)
1774{
1775	u32 p_limit1 = rdev->pm.dpm.tdp_limit;
1776	u32 p_limit2 = rdev->pm.dpm.near_tdp_limit;
1777	u32 k = dte_data->k;
1778	u32 t_max = dte_data->max_t;
1779	u32 t_split[5] = { 10, 15, 20, 25, 30 };
1780	u32 t_0 = dte_data->t0;
1781	u32 i;
1782
1783	if (p_limit2 != 0 && p_limit2 <= p_limit1) {
1784		dte_data->tdep_count = 3;
1785
1786		for (i = 0; i < k; i++) {
1787			dte_data->r[i] =
1788				(t_split[i] * (t_max - t_0/(u32)1000) * (1 << 14)) /
1789				(p_limit2  * (u32)100);
1790		}
1791
1792		dte_data->tdep_r[1] = dte_data->r[4] * 2;
1793
1794		for (i = 2; i < SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; i++) {
1795			dte_data->tdep_r[i] = dte_data->r[4];
1796		}
1797	} else {
1798		DRM_ERROR("Invalid PL2! DTE will not be updated.\n");
1799	}
1800}
1801
1802static void si_initialize_powertune_defaults(struct radeon_device *rdev)
1803{
1804	struct ni_power_info *ni_pi = ni_get_pi(rdev);
1805	struct si_power_info *si_pi = si_get_pi(rdev);
1806	bool update_dte_from_pl2 = false;
1807
1808	if (rdev->family == CHIP_TAHITI) {
1809		si_pi->cac_weights = cac_weights_tahiti;
1810		si_pi->lcac_config = lcac_tahiti;
1811		si_pi->cac_override = cac_override_tahiti;
1812		si_pi->powertune_data = &powertune_data_tahiti;
1813		si_pi->dte_data = dte_data_tahiti;
1814
1815		switch (rdev->pdev->device) {
1816		case 0x6798:
1817			si_pi->dte_data.enable_dte_by_default = true;
1818			break;
1819		case 0x6799:
1820			si_pi->dte_data = dte_data_new_zealand;
1821			break;
1822		case 0x6790:
1823		case 0x6791:
1824		case 0x6792:
1825		case 0x679E:
1826			si_pi->dte_data = dte_data_aruba_pro;
1827			update_dte_from_pl2 = true;
1828			break;
1829		case 0x679B:
1830			si_pi->dte_data = dte_data_malta;
1831			update_dte_from_pl2 = true;
1832			break;
1833		case 0x679A:
1834			si_pi->dte_data = dte_data_tahiti_pro;
1835			update_dte_from_pl2 = true;
1836			break;
1837		default:
1838			if (si_pi->dte_data.enable_dte_by_default == true)
1839				DRM_ERROR("DTE is not enabled!\n");
1840			break;
1841		}
1842	} else if (rdev->family == CHIP_PITCAIRN) {
1843		switch (rdev->pdev->device) {
1844		case 0x6810:
1845		case 0x6818:
1846			si_pi->cac_weights = cac_weights_pitcairn;
1847			si_pi->lcac_config = lcac_pitcairn;
1848			si_pi->cac_override = cac_override_pitcairn;
1849			si_pi->powertune_data = &powertune_data_pitcairn;
1850			si_pi->dte_data = dte_data_curacao_xt;
1851			update_dte_from_pl2 = true;
1852			break;
1853		case 0x6819:
1854		case 0x6811:
1855			si_pi->cac_weights = cac_weights_pitcairn;
1856			si_pi->lcac_config = lcac_pitcairn;
1857			si_pi->cac_override = cac_override_pitcairn;
1858			si_pi->powertune_data = &powertune_data_pitcairn;
1859			si_pi->dte_data = dte_data_curacao_pro;
1860			update_dte_from_pl2 = true;
1861			break;
1862		case 0x6800:
1863		case 0x6806:
1864			si_pi->cac_weights = cac_weights_pitcairn;
1865			si_pi->lcac_config = lcac_pitcairn;
1866			si_pi->cac_override = cac_override_pitcairn;
1867			si_pi->powertune_data = &powertune_data_pitcairn;
1868			si_pi->dte_data = dte_data_neptune_xt;
1869			update_dte_from_pl2 = true;
1870			break;
1871		default:
1872			si_pi->cac_weights = cac_weights_pitcairn;
1873			si_pi->lcac_config = lcac_pitcairn;
1874			si_pi->cac_override = cac_override_pitcairn;
1875			si_pi->powertune_data = &powertune_data_pitcairn;
1876			si_pi->dte_data = dte_data_pitcairn;
1877			break;
1878		}
1879	} else if (rdev->family == CHIP_VERDE) {
1880		si_pi->lcac_config = lcac_cape_verde;
1881		si_pi->cac_override = cac_override_cape_verde;
1882		si_pi->powertune_data = &powertune_data_cape_verde;
1883
1884		switch (rdev->pdev->device) {
1885		case 0x683B:
1886		case 0x683F:
1887		case 0x6829:
1888		case 0x6835:
1889			si_pi->cac_weights = cac_weights_cape_verde_pro;
1890			si_pi->dte_data = dte_data_cape_verde;
1891			break;
1892		case 0x682C:
1893			si_pi->cac_weights = cac_weights_cape_verde_pro;
1894			si_pi->dte_data = dte_data_sun_xt;
1895			update_dte_from_pl2 = true;
1896			break;
1897		case 0x6825:
1898		case 0x6827:
1899			si_pi->cac_weights = cac_weights_heathrow;
1900			si_pi->dte_data = dte_data_cape_verde;
1901			break;
1902		case 0x6824:
1903		case 0x682D:
1904			si_pi->cac_weights = cac_weights_chelsea_xt;
1905			si_pi->dte_data = dte_data_cape_verde;
1906			break;
1907		case 0x682F:
1908			si_pi->cac_weights = cac_weights_chelsea_pro;
1909			si_pi->dte_data = dte_data_cape_verde;
1910			break;
1911		case 0x6820:
1912			si_pi->cac_weights = cac_weights_heathrow;
1913			si_pi->dte_data = dte_data_venus_xtx;
1914			break;
1915		case 0x6821:
1916			si_pi->cac_weights = cac_weights_heathrow;
1917			si_pi->dte_data = dte_data_venus_xt;
1918			break;
1919		case 0x6823:
1920		case 0x682B:
1921		case 0x6822:
1922		case 0x682A:
1923			si_pi->cac_weights = cac_weights_chelsea_pro;
1924			si_pi->dte_data = dte_data_venus_pro;
1925			break;
1926		default:
1927			si_pi->cac_weights = cac_weights_cape_verde;
1928			si_pi->dte_data = dte_data_cape_verde;
1929			break;
1930		}
1931	} else if (rdev->family == CHIP_OLAND) {
1932		switch (rdev->pdev->device) {
1933		case 0x6601:
1934		case 0x6621:
1935		case 0x6603:
1936		case 0x6605:
1937			si_pi->cac_weights = cac_weights_mars_pro;
1938			si_pi->lcac_config = lcac_mars_pro;
1939			si_pi->cac_override = cac_override_oland;
1940			si_pi->powertune_data = &powertune_data_mars_pro;
1941			si_pi->dte_data = dte_data_mars_pro;
1942			update_dte_from_pl2 = true;
1943			break;
1944		case 0x6600:
1945		case 0x6606:
1946		case 0x6620:
1947		case 0x6604:
1948			si_pi->cac_weights = cac_weights_mars_xt;
1949			si_pi->lcac_config = lcac_mars_pro;
1950			si_pi->cac_override = cac_override_oland;
1951			si_pi->powertune_data = &powertune_data_mars_pro;
1952			si_pi->dte_data = dte_data_mars_pro;
1953			update_dte_from_pl2 = true;
1954			break;
1955		case 0x6611:
1956		case 0x6613:
1957		case 0x6608:
1958			si_pi->cac_weights = cac_weights_oland_pro;
1959			si_pi->lcac_config = lcac_mars_pro;
1960			si_pi->cac_override = cac_override_oland;
1961			si_pi->powertune_data = &powertune_data_mars_pro;
1962			si_pi->dte_data = dte_data_mars_pro;
1963			update_dte_from_pl2 = true;
1964			break;
1965		case 0x6610:
1966			si_pi->cac_weights = cac_weights_oland_xt;
1967			si_pi->lcac_config = lcac_mars_pro;
1968			si_pi->cac_override = cac_override_oland;
1969			si_pi->powertune_data = &powertune_data_mars_pro;
1970			si_pi->dte_data = dte_data_mars_pro;
1971			update_dte_from_pl2 = true;
1972			break;
1973		default:
1974			si_pi->cac_weights = cac_weights_oland;
1975			si_pi->lcac_config = lcac_oland;
1976			si_pi->cac_override = cac_override_oland;
1977			si_pi->powertune_data = &powertune_data_oland;
1978			si_pi->dte_data = dte_data_oland;
1979			break;
1980		}
1981	} else if (rdev->family == CHIP_HAINAN) {
1982		si_pi->cac_weights = cac_weights_hainan;
1983		si_pi->lcac_config = lcac_oland;
1984		si_pi->cac_override = cac_override_oland;
1985		si_pi->powertune_data = &powertune_data_hainan;
1986		si_pi->dte_data = dte_data_sun_xt;
1987		update_dte_from_pl2 = true;
1988	} else {
1989		DRM_ERROR("Unknown SI asic revision, failed to initialize PowerTune!\n");
1990		return;
1991	}
1992
1993	ni_pi->enable_power_containment = false;
1994	ni_pi->enable_cac = false;
1995	ni_pi->enable_sq_ramping = false;
1996	si_pi->enable_dte = false;
1997
1998	if (si_pi->powertune_data->enable_powertune_by_default) {
1999		ni_pi->enable_power_containment= true;
2000		ni_pi->enable_cac = true;
2001		if (si_pi->dte_data.enable_dte_by_default) {
2002			si_pi->enable_dte = true;
2003			if (update_dte_from_pl2)
2004				si_update_dte_from_pl2(rdev, &si_pi->dte_data);
2005
2006		}
2007		ni_pi->enable_sq_ramping = true;
2008	}
2009
2010	ni_pi->driver_calculate_cac_leakage = true;
2011	ni_pi->cac_configuration_required = true;
2012
2013	if (ni_pi->cac_configuration_required) {
2014		ni_pi->support_cac_long_term_average = true;
2015		si_pi->dyn_powertune_data.l2_lta_window_size =
2016			si_pi->powertune_data->l2_lta_window_size_default;
2017		si_pi->dyn_powertune_data.lts_truncate =
2018			si_pi->powertune_data->lts_truncate_default;
2019	} else {
2020		ni_pi->support_cac_long_term_average = false;
2021		si_pi->dyn_powertune_data.l2_lta_window_size = 0;
2022		si_pi->dyn_powertune_data.lts_truncate = 0;
2023	}
2024
2025	si_pi->dyn_powertune_data.disable_uvd_powertune = false;
2026}
2027
2028static u32 si_get_smc_power_scaling_factor(struct radeon_device *rdev)
2029{
2030	return 1;
2031}
2032
2033static u32 si_calculate_cac_wintime(struct radeon_device *rdev)
2034{
2035	u32 xclk;
2036	u32 wintime;
2037	u32 cac_window;
2038	u32 cac_window_size;
2039
2040	xclk = radeon_get_xclk(rdev);
2041
2042	if (xclk == 0)
2043		return 0;
2044
2045	cac_window = RREG32(CG_CAC_CTRL) & CAC_WINDOW_MASK;
2046	cac_window_size = ((cac_window & 0xFFFF0000) >> 16) * (cac_window & 0x0000FFFF);
2047
2048	wintime = (cac_window_size * 100) / xclk;
2049
2050	return wintime;
2051}
2052
2053static u32 si_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor)
2054{
2055	return power_in_watts;
2056}
2057
2058static int si_calculate_adjusted_tdp_limits(struct radeon_device *rdev,
2059					    bool adjust_polarity,
2060					    u32 tdp_adjustment,
2061					    u32 *tdp_limit,
2062					    u32 *near_tdp_limit)
2063{
2064	u32 adjustment_delta, max_tdp_limit;
2065
2066	if (tdp_adjustment > (u32)rdev->pm.dpm.tdp_od_limit)
2067		return -EINVAL;
2068
2069	max_tdp_limit = ((100 + 100) * rdev->pm.dpm.tdp_limit) / 100;
2070
2071	if (adjust_polarity) {
2072		*tdp_limit = ((100 + tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
2073		*near_tdp_limit = rdev->pm.dpm.near_tdp_limit_adjusted + (*tdp_limit - rdev->pm.dpm.tdp_limit);
2074	} else {
2075		*tdp_limit = ((100 - tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
2076		adjustment_delta  = rdev->pm.dpm.tdp_limit - *tdp_limit;
2077		if (adjustment_delta < rdev->pm.dpm.near_tdp_limit_adjusted)
2078			*near_tdp_limit = rdev->pm.dpm.near_tdp_limit_adjusted - adjustment_delta;
2079		else
2080			*near_tdp_limit = 0;
2081	}
2082
2083	if ((*tdp_limit <= 0) || (*tdp_limit > max_tdp_limit))
2084		return -EINVAL;
2085	if ((*near_tdp_limit <= 0) || (*near_tdp_limit > *tdp_limit))
2086		return -EINVAL;
2087
2088	return 0;
2089}
2090
2091static int si_populate_smc_tdp_limits(struct radeon_device *rdev,
2092				      struct radeon_ps *radeon_state)
2093{
2094	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2095	struct si_power_info *si_pi = si_get_pi(rdev);
2096
2097	if (ni_pi->enable_power_containment) {
2098		SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
2099		PP_SIslands_PAPMParameters *papm_parm;
2100		struct radeon_ppm_table *ppm = rdev->pm.dpm.dyn_state.ppm_table;
2101		u32 scaling_factor = si_get_smc_power_scaling_factor(rdev);
2102		u32 tdp_limit;
2103		u32 near_tdp_limit;
2104		int ret;
2105
2106		if (scaling_factor == 0)
2107			return -EINVAL;
2108
2109		memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
2110
2111		ret = si_calculate_adjusted_tdp_limits(rdev,
2112						       false, /* ??? */
2113						       rdev->pm.dpm.tdp_adjustment,
2114						       &tdp_limit,
2115						       &near_tdp_limit);
2116		if (ret)
2117			return ret;
2118
2119		smc_table->dpm2Params.TDPLimit =
2120			cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000);
2121		smc_table->dpm2Params.NearTDPLimit =
2122			cpu_to_be32(si_scale_power_for_smc(near_tdp_limit, scaling_factor) * 1000);
2123		smc_table->dpm2Params.SafePowerLimit =
2124			cpu_to_be32(si_scale_power_for_smc((near_tdp_limit * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
2125
2126		ret = si_copy_bytes_to_smc(rdev,
2127					   (si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
2128						 offsetof(PP_SIslands_DPM2Parameters, TDPLimit)),
2129					   (u8 *)(&(smc_table->dpm2Params.TDPLimit)),
2130					   sizeof(u32) * 3,
2131					   si_pi->sram_end);
2132		if (ret)
2133			return ret;
2134
2135		if (si_pi->enable_ppm) {
2136			papm_parm = &si_pi->papm_parm;
2137			memset(papm_parm, 0, sizeof(PP_SIslands_PAPMParameters));
2138			papm_parm->NearTDPLimitTherm = cpu_to_be32(ppm->dgpu_tdp);
2139			papm_parm->dGPU_T_Limit = cpu_to_be32(ppm->tj_max);
2140			papm_parm->dGPU_T_Warning = cpu_to_be32(95);
2141			papm_parm->dGPU_T_Hysteresis = cpu_to_be32(5);
2142			papm_parm->PlatformPowerLimit = 0xffffffff;
2143			papm_parm->NearTDPLimitPAPM = 0xffffffff;
2144
2145			ret = si_copy_bytes_to_smc(rdev, si_pi->papm_cfg_table_start,
2146						   (u8 *)papm_parm,
2147						   sizeof(PP_SIslands_PAPMParameters),
2148						   si_pi->sram_end);
2149			if (ret)
2150				return ret;
2151		}
2152	}
2153	return 0;
2154}
2155
2156static int si_populate_smc_tdp_limits_2(struct radeon_device *rdev,
2157					struct radeon_ps *radeon_state)
2158{
2159	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2160	struct si_power_info *si_pi = si_get_pi(rdev);
2161
2162	if (ni_pi->enable_power_containment) {
2163		SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
2164		u32 scaling_factor = si_get_smc_power_scaling_factor(rdev);
2165		int ret;
2166
2167		memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
2168
2169		smc_table->dpm2Params.NearTDPLimit =
2170			cpu_to_be32(si_scale_power_for_smc(rdev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000);
2171		smc_table->dpm2Params.SafePowerLimit =
2172			cpu_to_be32(si_scale_power_for_smc((rdev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
2173
2174		ret = si_copy_bytes_to_smc(rdev,
2175					   (si_pi->state_table_start +
2176					    offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
2177					    offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)),
2178					   (u8 *)(&(smc_table->dpm2Params.NearTDPLimit)),
2179					   sizeof(u32) * 2,
2180					   si_pi->sram_end);
2181		if (ret)
2182			return ret;
2183	}
2184
2185	return 0;
2186}
2187
2188static u16 si_calculate_power_efficiency_ratio(struct radeon_device *rdev,
2189					       const u16 prev_std_vddc,
2190					       const u16 curr_std_vddc)
2191{
2192	u64 margin = (u64)SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN;
2193	u64 prev_vddc = (u64)prev_std_vddc;
2194	u64 curr_vddc = (u64)curr_std_vddc;
2195	u64 pwr_efficiency_ratio, n, d;
2196
2197	if ((prev_vddc == 0) || (curr_vddc == 0))
2198		return 0;
2199
2200	n = div64_u64((u64)1024 * curr_vddc * curr_vddc * ((u64)1000 + margin), (u64)1000);
2201	d = prev_vddc * prev_vddc;
2202	pwr_efficiency_ratio = div64_u64(n, d);
2203
2204	if (pwr_efficiency_ratio > (u64)0xFFFF)
2205		return 0;
2206
2207	return (u16)pwr_efficiency_ratio;
2208}
2209
2210static bool si_should_disable_uvd_powertune(struct radeon_device *rdev,
2211					    struct radeon_ps *radeon_state)
2212{
2213	struct si_power_info *si_pi = si_get_pi(rdev);
2214
2215	if (si_pi->dyn_powertune_data.disable_uvd_powertune &&
2216	    radeon_state->vclk && radeon_state->dclk)
2217		return true;
2218
2219	return false;
2220}
2221
2222static int si_populate_power_containment_values(struct radeon_device *rdev,
2223						struct radeon_ps *radeon_state,
2224						SISLANDS_SMC_SWSTATE *smc_state)
2225{
2226	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
2227	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2228	struct ni_ps *state = ni_get_ps(radeon_state);
2229	SISLANDS_SMC_VOLTAGE_VALUE vddc;
2230	u32 prev_sclk;
2231	u32 max_sclk;
2232	u32 min_sclk;
2233	u16 prev_std_vddc;
2234	u16 curr_std_vddc;
2235	int i;
2236	u16 pwr_efficiency_ratio;
2237	u8 max_ps_percent;
2238	bool disable_uvd_power_tune;
2239	int ret;
2240
2241	if (ni_pi->enable_power_containment == false)
2242		return 0;
2243
2244	if (state->performance_level_count == 0)
2245		return -EINVAL;
2246
2247	if (smc_state->levelCount != state->performance_level_count)
2248		return -EINVAL;
2249
2250	disable_uvd_power_tune = si_should_disable_uvd_powertune(rdev, radeon_state);
2251
2252	smc_state->levels[0].dpm2.MaxPS = 0;
2253	smc_state->levels[0].dpm2.NearTDPDec = 0;
2254	smc_state->levels[0].dpm2.AboveSafeInc = 0;
2255	smc_state->levels[0].dpm2.BelowSafeInc = 0;
2256	smc_state->levels[0].dpm2.PwrEfficiencyRatio = 0;
2257
2258	for (i = 1; i < state->performance_level_count; i++) {
2259		prev_sclk = state->performance_levels[i-1].sclk;
2260		max_sclk  = state->performance_levels[i].sclk;
2261		if (i == 1)
2262			max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_M;
2263		else
2264			max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_H;
2265
2266		if (prev_sclk > max_sclk)
2267			return -EINVAL;
2268
2269		if ((max_ps_percent == 0) ||
2270		    (prev_sclk == max_sclk) ||
2271		    disable_uvd_power_tune) {
2272			min_sclk = max_sclk;
2273		} else if (i == 1) {
2274			min_sclk = prev_sclk;
2275		} else {
2276			min_sclk = (prev_sclk * (u32)max_ps_percent) / 100;
2277		}
2278
2279		if (min_sclk < state->performance_levels[0].sclk)
2280			min_sclk = state->performance_levels[0].sclk;
2281
2282		if (min_sclk == 0)
2283			return -EINVAL;
2284
2285		ret = si_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
2286						state->performance_levels[i-1].vddc, &vddc);
2287		if (ret)
2288			return ret;
2289
2290		ret = si_get_std_voltage_value(rdev, &vddc, &prev_std_vddc);
2291		if (ret)
2292			return ret;
2293
2294		ret = si_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
2295						state->performance_levels[i].vddc, &vddc);
2296		if (ret)
2297			return ret;
2298
2299		ret = si_get_std_voltage_value(rdev, &vddc, &curr_std_vddc);
2300		if (ret)
2301			return ret;
2302
2303		pwr_efficiency_ratio = si_calculate_power_efficiency_ratio(rdev,
2304									   prev_std_vddc, curr_std_vddc);
2305
2306		smc_state->levels[i].dpm2.MaxPS = (u8)((SISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk);
2307		smc_state->levels[i].dpm2.NearTDPDec = SISLANDS_DPM2_NEAR_TDP_DEC;
2308		smc_state->levels[i].dpm2.AboveSafeInc = SISLANDS_DPM2_ABOVE_SAFE_INC;
2309		smc_state->levels[i].dpm2.BelowSafeInc = SISLANDS_DPM2_BELOW_SAFE_INC;
2310		smc_state->levels[i].dpm2.PwrEfficiencyRatio = cpu_to_be16(pwr_efficiency_ratio);
2311	}
2312
2313	return 0;
2314}
2315
2316static int si_populate_sq_ramping_values(struct radeon_device *rdev,
2317					 struct radeon_ps *radeon_state,
2318					 SISLANDS_SMC_SWSTATE *smc_state)
2319{
2320	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2321	struct ni_ps *state = ni_get_ps(radeon_state);
2322	u32 sq_power_throttle, sq_power_throttle2;
2323	bool enable_sq_ramping = ni_pi->enable_sq_ramping;
2324	int i;
2325
2326	if (state->performance_level_count == 0)
2327		return -EINVAL;
2328
2329	if (smc_state->levelCount != state->performance_level_count)
2330		return -EINVAL;
2331
2332	if (rdev->pm.dpm.sq_ramping_threshold == 0)
2333		return -EINVAL;
2334
2335	if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT))
2336		enable_sq_ramping = false;
2337
2338	if (SISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT))
2339		enable_sq_ramping = false;
2340
2341	if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT))
2342		enable_sq_ramping = false;
2343
2344	if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
2345		enable_sq_ramping = false;
2346
2347	if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
2348		enable_sq_ramping = false;
2349
2350	for (i = 0; i < state->performance_level_count; i++) {
2351		sq_power_throttle = 0;
2352		sq_power_throttle2 = 0;
2353
2354		if ((state->performance_levels[i].sclk >= rdev->pm.dpm.sq_ramping_threshold) &&
2355		    enable_sq_ramping) {
2356			sq_power_throttle |= MAX_POWER(SISLANDS_DPM2_SQ_RAMP_MAX_POWER);
2357			sq_power_throttle |= MIN_POWER(SISLANDS_DPM2_SQ_RAMP_MIN_POWER);
2358			sq_power_throttle2 |= MAX_POWER_DELTA(SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA);
2359			sq_power_throttle2 |= STI_SIZE(SISLANDS_DPM2_SQ_RAMP_STI_SIZE);
2360			sq_power_throttle2 |= LTI_RATIO(SISLANDS_DPM2_SQ_RAMP_LTI_RATIO);
2361		} else {
2362			sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK;
2363			sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
2364		}
2365
2366		smc_state->levels[i].SQPowerThrottle = cpu_to_be32(sq_power_throttle);
2367		smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2);
2368	}
2369
2370	return 0;
2371}
2372
2373static int si_enable_power_containment(struct radeon_device *rdev,
2374				       struct radeon_ps *radeon_new_state,
2375				       bool enable)
2376{
2377	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2378	PPSMC_Result smc_result;
2379	int ret = 0;
2380
2381	if (ni_pi->enable_power_containment) {
2382		if (enable) {
2383			if (!si_should_disable_uvd_powertune(rdev, radeon_new_state)) {
2384				smc_result = si_send_msg_to_smc(rdev, PPSMC_TDPClampingActive);
2385				if (smc_result != PPSMC_Result_OK) {
2386					ret = -EINVAL;
2387					ni_pi->pc_enabled = false;
2388				} else {
2389					ni_pi->pc_enabled = true;
2390				}
2391			}
2392		} else {
2393			smc_result = si_send_msg_to_smc(rdev, PPSMC_TDPClampingInactive);
2394			if (smc_result != PPSMC_Result_OK)
2395				ret = -EINVAL;
2396			ni_pi->pc_enabled = false;
2397		}
2398	}
2399
2400	return ret;
2401}
2402
2403static int si_initialize_smc_dte_tables(struct radeon_device *rdev)
2404{
2405	struct si_power_info *si_pi = si_get_pi(rdev);
2406	int ret = 0;
2407	struct si_dte_data *dte_data = &si_pi->dte_data;
2408	Smc_SIslands_DTE_Configuration *dte_tables = NULL;
2409	u32 table_size;
2410	u8 tdep_count;
2411	u32 i;
2412
2413	if (dte_data == NULL)
2414		si_pi->enable_dte = false;
2415
2416	if (si_pi->enable_dte == false)
2417		return 0;
2418
2419	if (dte_data->k <= 0)
2420		return -EINVAL;
2421
2422	dte_tables = kzalloc(sizeof(Smc_SIslands_DTE_Configuration), GFP_KERNEL);
2423	if (dte_tables == NULL) {
2424		si_pi->enable_dte = false;
2425		return -ENOMEM;
2426	}
2427
2428	table_size = dte_data->k;
2429
2430	if (table_size > SMC_SISLANDS_DTE_MAX_FILTER_STAGES)
2431		table_size = SMC_SISLANDS_DTE_MAX_FILTER_STAGES;
2432
2433	tdep_count = dte_data->tdep_count;
2434	if (tdep_count > SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE)
2435		tdep_count = SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE;
2436
2437	dte_tables->K = cpu_to_be32(table_size);
2438	dte_tables->T0 = cpu_to_be32(dte_data->t0);
2439	dte_tables->MaxT = cpu_to_be32(dte_data->max_t);
2440	dte_tables->WindowSize = dte_data->window_size;
2441	dte_tables->temp_select = dte_data->temp_select;
2442	dte_tables->DTE_mode = dte_data->dte_mode;
2443	dte_tables->Tthreshold = cpu_to_be32(dte_data->t_threshold);
2444
2445	if (tdep_count > 0)
2446		table_size--;
2447
2448	for (i = 0; i < table_size; i++) {
2449		dte_tables->tau[i] = cpu_to_be32(dte_data->tau[i]);
2450		dte_tables->R[i]   = cpu_to_be32(dte_data->r[i]);
2451	}
2452
2453	dte_tables->Tdep_count = tdep_count;
2454
2455	for (i = 0; i < (u32)tdep_count; i++) {
2456		dte_tables->T_limits[i] = dte_data->t_limits[i];
2457		dte_tables->Tdep_tau[i] = cpu_to_be32(dte_data->tdep_tau[i]);
2458		dte_tables->Tdep_R[i] = cpu_to_be32(dte_data->tdep_r[i]);
2459	}
2460
2461	ret = si_copy_bytes_to_smc(rdev, si_pi->dte_table_start, (u8 *)dte_tables,
2462				   sizeof(Smc_SIslands_DTE_Configuration), si_pi->sram_end);
2463	kfree(dte_tables);
2464
2465	return ret;
2466}
2467
2468static int si_get_cac_std_voltage_max_min(struct radeon_device *rdev,
2469					  u16 *max, u16 *min)
2470{
2471	struct si_power_info *si_pi = si_get_pi(rdev);
2472	struct radeon_cac_leakage_table *table =
2473		&rdev->pm.dpm.dyn_state.cac_leakage_table;
2474	u32 i;
2475	u32 v0_loadline;
2476
2477
2478	if (table == NULL)
2479		return -EINVAL;
2480
2481	*max = 0;
2482	*min = 0xFFFF;
2483
2484	for (i = 0; i < table->count; i++) {
2485		if (table->entries[i].vddc > *max)
2486			*max = table->entries[i].vddc;
2487		if (table->entries[i].vddc < *min)
2488			*min = table->entries[i].vddc;
2489	}
2490
2491	if (si_pi->powertune_data->lkge_lut_v0_percent > 100)
2492		return -EINVAL;
2493
2494	v0_loadline = (*min) * (100 - si_pi->powertune_data->lkge_lut_v0_percent) / 100;
2495
2496	if (v0_loadline > 0xFFFFUL)
2497		return -EINVAL;
2498
2499	*min = (u16)v0_loadline;
2500
2501	if ((*min > *max) || (*max == 0) || (*min == 0))
2502		return -EINVAL;
2503
2504	return 0;
2505}
2506
2507static u16 si_get_cac_std_voltage_step(u16 max, u16 min)
2508{
2509	return ((max - min) + (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)) /
2510		SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES;
2511}
2512
2513static int si_init_dte_leakage_table(struct radeon_device *rdev,
2514				     PP_SIslands_CacConfig *cac_tables,
2515				     u16 vddc_max, u16 vddc_min, u16 vddc_step,
2516				     u16 t0, u16 t_step)
2517{
2518	struct si_power_info *si_pi = si_get_pi(rdev);
2519	u32 leakage;
2520	unsigned int i, j;
2521	s32 t;
2522	u32 smc_leakage;
2523	u32 scaling_factor;
2524	u16 voltage;
2525
2526	scaling_factor = si_get_smc_power_scaling_factor(rdev);
2527
2528	for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) {
2529		t = (1000 * (i * t_step + t0));
2530
2531		for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
2532			voltage = vddc_max - (vddc_step * j);
2533
2534			si_calculate_leakage_for_v_and_t(rdev,
2535							 &si_pi->powertune_data->leakage_coefficients,
2536							 voltage,
2537							 t,
2538							 si_pi->dyn_powertune_data.cac_leakage,
2539							 &leakage);
2540
2541			smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4;
2542
2543			if (smc_leakage > 0xFFFF)
2544				smc_leakage = 0xFFFF;
2545
2546			cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] =
2547				cpu_to_be16((u16)smc_leakage);
2548		}
2549	}
2550	return 0;
2551}
2552
2553static int si_init_simplified_leakage_table(struct radeon_device *rdev,
2554					    PP_SIslands_CacConfig *cac_tables,
2555					    u16 vddc_max, u16 vddc_min, u16 vddc_step)
2556{
2557	struct si_power_info *si_pi = si_get_pi(rdev);
2558	u32 leakage;
2559	unsigned int i, j;
2560	u32 smc_leakage;
2561	u32 scaling_factor;
2562	u16 voltage;
2563
2564	scaling_factor = si_get_smc_power_scaling_factor(rdev);
2565
2566	for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
2567		voltage = vddc_max - (vddc_step * j);
2568
2569		si_calculate_leakage_for_v(rdev,
2570					   &si_pi->powertune_data->leakage_coefficients,
2571					   si_pi->powertune_data->fixed_kt,
2572					   voltage,
2573					   si_pi->dyn_powertune_data.cac_leakage,
2574					   &leakage);
2575
2576		smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4;
2577
2578		if (smc_leakage > 0xFFFF)
2579			smc_leakage = 0xFFFF;
2580
2581		for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++)
2582			cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] =
2583				cpu_to_be16((u16)smc_leakage);
2584	}
2585	return 0;
2586}
2587
2588static int si_initialize_smc_cac_tables(struct radeon_device *rdev)
2589{
2590	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2591	struct si_power_info *si_pi = si_get_pi(rdev);
2592	PP_SIslands_CacConfig *cac_tables = NULL;
2593	u16 vddc_max, vddc_min, vddc_step;
2594	u16 t0, t_step;
2595	u32 load_line_slope, reg;
2596	int ret = 0;
2597	u32 ticks_per_us = radeon_get_xclk(rdev) / 100;
2598
2599	if (ni_pi->enable_cac == false)
2600		return 0;
2601
2602	cac_tables = kzalloc(sizeof(PP_SIslands_CacConfig), GFP_KERNEL);
2603	if (!cac_tables)
2604		return -ENOMEM;
2605
2606	reg = RREG32(CG_CAC_CTRL) & ~CAC_WINDOW_MASK;
2607	reg |= CAC_WINDOW(si_pi->powertune_data->cac_window);
2608	WREG32(CG_CAC_CTRL, reg);
2609
2610	si_pi->dyn_powertune_data.cac_leakage = rdev->pm.dpm.cac_leakage;
2611	si_pi->dyn_powertune_data.dc_pwr_value =
2612		si_pi->powertune_data->dc_cac[NISLANDS_DCCAC_LEVEL_0];
2613	si_pi->dyn_powertune_data.wintime = si_calculate_cac_wintime(rdev);
2614	si_pi->dyn_powertune_data.shift_n = si_pi->powertune_data->shift_n_default;
2615
2616	si_pi->dyn_powertune_data.leakage_minimum_temperature = 80 * 1000;
2617
2618	ret = si_get_cac_std_voltage_max_min(rdev, &vddc_max, &vddc_min);
2619	if (ret)
2620		goto done_free;
2621
2622	vddc_step = si_get_cac_std_voltage_step(vddc_max, vddc_min);
2623	vddc_min = vddc_max - (vddc_step * (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1));
2624	t_step = 4;
2625	t0 = 60;
2626
2627	if (si_pi->enable_dte || ni_pi->driver_calculate_cac_leakage)
2628		ret = si_init_dte_leakage_table(rdev, cac_tables,
2629						vddc_max, vddc_min, vddc_step,
2630						t0, t_step);
2631	else
2632		ret = si_init_simplified_leakage_table(rdev, cac_tables,
2633						       vddc_max, vddc_min, vddc_step);
2634	if (ret)
2635		goto done_free;
2636
2637	load_line_slope = ((u32)rdev->pm.dpm.load_line_slope << SMC_SISLANDS_SCALE_R) / 100;
2638
2639	cac_tables->l2numWin_TDP = cpu_to_be32(si_pi->dyn_powertune_data.l2_lta_window_size);
2640	cac_tables->lts_truncate_n = si_pi->dyn_powertune_data.lts_truncate;
2641	cac_tables->SHIFT_N = si_pi->dyn_powertune_data.shift_n;
2642	cac_tables->lkge_lut_V0 = cpu_to_be32((u32)vddc_min);
2643	cac_tables->lkge_lut_Vstep = cpu_to_be32((u32)vddc_step);
2644	cac_tables->R_LL = cpu_to_be32(load_line_slope);
2645	cac_tables->WinTime = cpu_to_be32(si_pi->dyn_powertune_data.wintime);
2646	cac_tables->calculation_repeats = cpu_to_be32(2);
2647	cac_tables->dc_cac = cpu_to_be32(0);
2648	cac_tables->log2_PG_LKG_SCALE = 12;
2649	cac_tables->cac_temp = si_pi->powertune_data->operating_temp;
2650	cac_tables->lkge_lut_T0 = cpu_to_be32((u32)t0);
2651	cac_tables->lkge_lut_Tstep = cpu_to_be32((u32)t_step);
2652
2653	ret = si_copy_bytes_to_smc(rdev, si_pi->cac_table_start, (u8 *)cac_tables,
2654				   sizeof(PP_SIslands_CacConfig), si_pi->sram_end);
2655
2656	if (ret)
2657		goto done_free;
2658
2659	ret = si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_ticks_per_us, ticks_per_us);
2660
2661done_free:
2662	if (ret) {
2663		ni_pi->enable_cac = false;
2664		ni_pi->enable_power_containment = false;
2665	}
2666
2667	kfree(cac_tables);
2668
2669	return 0;
2670}
2671
2672static int si_program_cac_config_registers(struct radeon_device *rdev,
2673					   const struct si_cac_config_reg *cac_config_regs)
2674{
2675	const struct si_cac_config_reg *config_regs = cac_config_regs;
2676	u32 data = 0, offset;
2677
2678	if (!config_regs)
2679		return -EINVAL;
2680
2681	while (config_regs->offset != 0xFFFFFFFF) {
2682		switch (config_regs->type) {
2683		case SISLANDS_CACCONFIG_CGIND:
2684			offset = SMC_CG_IND_START + config_regs->offset;
2685			if (offset < SMC_CG_IND_END)
2686				data = RREG32_SMC(offset);
2687			break;
2688		default:
2689			data = RREG32(config_regs->offset << 2);
2690			break;
2691		}
2692
2693		data &= ~config_regs->mask;
2694		data |= ((config_regs->value << config_regs->shift) & config_regs->mask);
2695
2696		switch (config_regs->type) {
2697		case SISLANDS_CACCONFIG_CGIND:
2698			offset = SMC_CG_IND_START + config_regs->offset;
2699			if (offset < SMC_CG_IND_END)
2700				WREG32_SMC(offset, data);
2701			break;
2702		default:
2703			WREG32(config_regs->offset << 2, data);
2704			break;
2705		}
2706		config_regs++;
2707	}
2708	return 0;
2709}
2710
2711static int si_initialize_hardware_cac_manager(struct radeon_device *rdev)
2712{
2713	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2714	struct si_power_info *si_pi = si_get_pi(rdev);
2715	int ret;
2716
2717	if ((ni_pi->enable_cac == false) ||
2718	    (ni_pi->cac_configuration_required == false))
2719		return 0;
2720
2721	ret = si_program_cac_config_registers(rdev, si_pi->lcac_config);
2722	if (ret)
2723		return ret;
2724	ret = si_program_cac_config_registers(rdev, si_pi->cac_override);
2725	if (ret)
2726		return ret;
2727	ret = si_program_cac_config_registers(rdev, si_pi->cac_weights);
2728	if (ret)
2729		return ret;
2730
2731	return 0;
2732}
2733
2734static int si_enable_smc_cac(struct radeon_device *rdev,
2735			     struct radeon_ps *radeon_new_state,
2736			     bool enable)
2737{
2738	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2739	struct si_power_info *si_pi = si_get_pi(rdev);
2740	PPSMC_Result smc_result;
2741	int ret = 0;
2742
2743	if (ni_pi->enable_cac) {
2744		if (enable) {
2745			if (!si_should_disable_uvd_powertune(rdev, radeon_new_state)) {
2746				if (ni_pi->support_cac_long_term_average) {
2747					smc_result = si_send_msg_to_smc(rdev, PPSMC_CACLongTermAvgEnable);
2748					if (smc_result != PPSMC_Result_OK)
2749						ni_pi->support_cac_long_term_average = false;
2750				}
2751
2752				smc_result = si_send_msg_to_smc(rdev, PPSMC_MSG_EnableCac);
2753				if (smc_result != PPSMC_Result_OK) {
2754					ret = -EINVAL;
2755					ni_pi->cac_enabled = false;
2756				} else {
2757					ni_pi->cac_enabled = true;
2758				}
2759
2760				if (si_pi->enable_dte) {
2761					smc_result = si_send_msg_to_smc(rdev, PPSMC_MSG_EnableDTE);
2762					if (smc_result != PPSMC_Result_OK)
2763						ret = -EINVAL;
2764				}
2765			}
2766		} else if (ni_pi->cac_enabled) {
2767			if (si_pi->enable_dte)
2768				smc_result = si_send_msg_to_smc(rdev, PPSMC_MSG_DisableDTE);
2769
2770			smc_result = si_send_msg_to_smc(rdev, PPSMC_MSG_DisableCac);
2771
2772			ni_pi->cac_enabled = false;
2773
2774			if (ni_pi->support_cac_long_term_average)
2775				smc_result = si_send_msg_to_smc(rdev, PPSMC_CACLongTermAvgDisable);
2776		}
2777	}
2778	return ret;
2779}
2780
2781static int si_init_smc_spll_table(struct radeon_device *rdev)
2782{
2783	struct ni_power_info *ni_pi = ni_get_pi(rdev);
2784	struct si_power_info *si_pi = si_get_pi(rdev);
2785	SMC_SISLANDS_SPLL_DIV_TABLE *spll_table;
2786	SISLANDS_SMC_SCLK_VALUE sclk_params;
2787	u32 fb_div, p_div;
2788	u32 clk_s, clk_v;
2789	u32 sclk = 0;
2790	int ret = 0;
2791	u32 tmp;
2792	int i;
2793
2794	if (si_pi->spll_table_start == 0)
2795		return -EINVAL;
2796
2797	spll_table = kzalloc(sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), GFP_KERNEL);
2798	if (spll_table == NULL)
2799		return -ENOMEM;
2800
2801	for (i = 0; i < 256; i++) {
2802		ret = si_calculate_sclk_params(rdev, sclk, &sclk_params);
2803		if (ret)
2804			break;
2805
2806		p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT;
2807		fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT;
2808		clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT;
2809		clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT;
2810
2811		fb_div &= ~0x00001FFF;
2812		fb_div >>= 1;
2813		clk_v >>= 6;
2814
2815		if (p_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT))
2816			ret = -EINVAL;
2817		if (fb_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT))
2818			ret = -EINVAL;
2819		if (clk_s & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
2820			ret = -EINVAL;
2821		if (clk_v & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))
2822			ret = -EINVAL;
2823
2824		if (ret)
2825			break;
2826
2827		tmp = ((fb_div << SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) |
2828			((p_div << SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK);
2829		spll_table->freq[i] = cpu_to_be32(tmp);
2830
2831		tmp = ((clk_v << SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK) |
2832			((clk_s << SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK);
2833		spll_table->ss[i] = cpu_to_be32(tmp);
2834
2835		sclk += 512;
2836	}
2837
2838
2839	if (!ret)
2840		ret = si_copy_bytes_to_smc(rdev, si_pi->spll_table_start,
2841					   (u8 *)spll_table, sizeof(SMC_SISLANDS_SPLL_DIV_TABLE),
2842					   si_pi->sram_end);
2843
2844	if (ret)
2845		ni_pi->enable_power_containment = false;
2846
2847	kfree(spll_table);
2848
2849	return ret;
2850}
2851
2852static u16 si_get_lower_of_leakage_and_vce_voltage(struct radeon_device *rdev,
2853						   u16 vce_voltage)
2854{
2855	u16 highest_leakage = 0;
2856	struct si_power_info *si_pi = si_get_pi(rdev);
2857	int i;
2858
2859	for (i = 0; i < si_pi->leakage_voltage.count; i++){
2860		if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage)
2861			highest_leakage = si_pi->leakage_voltage.entries[i].voltage;
2862	}
2863
2864	if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage))
2865		return highest_leakage;
2866
2867	return vce_voltage;
2868}
2869
2870static int si_get_vce_clock_voltage(struct radeon_device *rdev,
2871				    u32 evclk, u32 ecclk, u16 *voltage)
2872{
2873	u32 i;
2874	int ret = -EINVAL;
2875	struct radeon_vce_clock_voltage_dependency_table *table =
2876		&rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
2877
2878	if (((evclk == 0) && (ecclk == 0)) ||
2879	    (table && (table->count == 0))) {
2880		*voltage = 0;
2881		return 0;
2882	}
2883
2884	for (i = 0; i < table->count; i++) {
2885		if ((evclk <= table->entries[i].evclk) &&
2886		    (ecclk <= table->entries[i].ecclk)) {
2887			*voltage = table->entries[i].v;
2888			ret = 0;
2889			break;
2890		}
2891	}
2892
2893	/* if no match return the highest voltage */
2894	if (ret)
2895		*voltage = table->entries[table->count - 1].v;
2896
2897	*voltage = si_get_lower_of_leakage_and_vce_voltage(rdev, *voltage);
2898
2899	return ret;
2900}
2901
2902static void si_apply_state_adjust_rules(struct radeon_device *rdev,
2903					struct radeon_ps *rps)
2904{
2905	struct ni_ps *ps = ni_get_ps(rps);
2906	struct radeon_clock_and_voltage_limits *max_limits;
2907	bool disable_mclk_switching = false;
2908	bool disable_sclk_switching = false;
2909	u32 mclk, sclk;
2910	u16 vddc, vddci, min_vce_voltage = 0;
2911	u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
2912	u32 max_sclk = 0, max_mclk = 0;
2913	int i;
2914
2915	if (rdev->family == CHIP_HAINAN) {
2916		if ((rdev->pdev->revision == 0x81) ||
2917		    (rdev->pdev->revision == 0xC3) ||
2918		    (rdev->pdev->device == 0x6664) ||
2919		    (rdev->pdev->device == 0x6665) ||
2920		    (rdev->pdev->device == 0x6667)) {
2921			max_sclk = 75000;
2922		}
2923		if ((rdev->pdev->revision == 0xC3) ||
2924		    (rdev->pdev->device == 0x6665)) {
2925			max_sclk = 60000;
2926			max_mclk = 80000;
2927		}
2928	} else if (rdev->family == CHIP_OLAND) {
2929		if ((rdev->pdev->revision == 0xC7) ||
2930		    (rdev->pdev->revision == 0x80) ||
2931		    (rdev->pdev->revision == 0x81) ||
2932		    (rdev->pdev->revision == 0x83) ||
2933		    (rdev->pdev->revision == 0x87) ||
2934		    (rdev->pdev->device == 0x6604) ||
2935		    (rdev->pdev->device == 0x6605)) {
2936			max_sclk = 75000;
2937		}
2938
2939		if (rdev->pm.dpm.high_pixelclock_count > 1)
2940			disable_sclk_switching = true;
2941	}
2942
2943	if (rps->vce_active) {
2944		rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
2945		rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
2946		si_get_vce_clock_voltage(rdev, rps->evclk, rps->ecclk,
2947					 &min_vce_voltage);
2948	} else {
2949		rps->evclk = 0;
2950		rps->ecclk = 0;
2951	}
2952
2953	if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
2954	    ni_dpm_vblank_too_short(rdev))
2955		disable_mclk_switching = true;
2956
2957	if (rps->vclk || rps->dclk) {
2958		disable_mclk_switching = true;
2959		disable_sclk_switching = true;
2960	}
2961
2962	if (rdev->pm.dpm.ac_power)
2963		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
2964	else
2965		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
2966
2967	for (i = ps->performance_level_count - 2; i >= 0; i--) {
2968		if (ps->performance_levels[i].vddc > ps->performance_levels[i+1].vddc)
2969			ps->performance_levels[i].vddc = ps->performance_levels[i+1].vddc;
2970	}
2971	if (rdev->pm.dpm.ac_power == false) {
2972		for (i = 0; i < ps->performance_level_count; i++) {
2973			if (ps->performance_levels[i].mclk > max_limits->mclk)
2974				ps->performance_levels[i].mclk = max_limits->mclk;
2975			if (ps->performance_levels[i].sclk > max_limits->sclk)
2976				ps->performance_levels[i].sclk = max_limits->sclk;
2977			if (ps->performance_levels[i].vddc > max_limits->vddc)
2978				ps->performance_levels[i].vddc = max_limits->vddc;
2979			if (ps->performance_levels[i].vddci > max_limits->vddci)
2980				ps->performance_levels[i].vddci = max_limits->vddci;
2981		}
2982	}
2983
2984	/* limit clocks to max supported clocks based on voltage dependency tables */
2985	btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
2986							&max_sclk_vddc);
2987	btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
2988							&max_mclk_vddci);
2989	btc_get_max_clock_from_voltage_dependency_table(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
2990							&max_mclk_vddc);
2991
2992	for (i = 0; i < ps->performance_level_count; i++) {
2993		if (max_sclk_vddc) {
2994			if (ps->performance_levels[i].sclk > max_sclk_vddc)
2995				ps->performance_levels[i].sclk = max_sclk_vddc;
2996		}
2997		if (max_mclk_vddci) {
2998			if (ps->performance_levels[i].mclk > max_mclk_vddci)
2999				ps->performance_levels[i].mclk = max_mclk_vddci;
3000		}
3001		if (max_mclk_vddc) {
3002			if (ps->performance_levels[i].mclk > max_mclk_vddc)
3003				ps->performance_levels[i].mclk = max_mclk_vddc;
3004		}
3005		if (max_mclk) {
3006			if (ps->performance_levels[i].mclk > max_mclk)
3007				ps->performance_levels[i].mclk = max_mclk;
3008		}
3009		if (max_sclk) {
3010			if (ps->performance_levels[i].sclk > max_sclk)
3011				ps->performance_levels[i].sclk = max_sclk;
3012		}
3013	}
3014
3015	/* XXX validate the min clocks required for display */
3016
3017	if (disable_mclk_switching) {
3018		mclk  = ps->performance_levels[ps->performance_level_count - 1].mclk;
3019		vddci = ps->performance_levels[ps->performance_level_count - 1].vddci;
3020	} else {
3021		mclk = ps->performance_levels[0].mclk;
3022		vddci = ps->performance_levels[0].vddci;
3023	}
3024
3025	if (disable_sclk_switching) {
3026		sclk = ps->performance_levels[ps->performance_level_count - 1].sclk;
3027		vddc = ps->performance_levels[ps->performance_level_count - 1].vddc;
3028	} else {
3029		sclk = ps->performance_levels[0].sclk;
3030		vddc = ps->performance_levels[0].vddc;
3031	}
3032
3033	if (rps->vce_active) {
3034		if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
3035			sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
3036		if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk)
3037			mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk;
3038	}
3039
3040	/* adjusted low state */
3041	ps->performance_levels[0].sclk = sclk;
3042	ps->performance_levels[0].mclk = mclk;
3043	ps->performance_levels[0].vddc = vddc;
3044	ps->performance_levels[0].vddci = vddci;
3045
3046	if (disable_sclk_switching) {
3047		sclk = ps->performance_levels[0].sclk;
3048		for (i = 1; i < ps->performance_level_count; i++) {
3049			if (sclk < ps->performance_levels[i].sclk)
3050				sclk = ps->performance_levels[i].sclk;
3051		}
3052		for (i = 0; i < ps->performance_level_count; i++) {
3053			ps->performance_levels[i].sclk = sclk;
3054			ps->performance_levels[i].vddc = vddc;
3055		}
3056	} else {
3057		for (i = 1; i < ps->performance_level_count; i++) {
3058			if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
3059				ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
3060			if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
3061				ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
3062		}
3063	}
3064
3065	if (disable_mclk_switching) {
3066		mclk = ps->performance_levels[0].mclk;
3067		for (i = 1; i < ps->performance_level_count; i++) {
3068			if (mclk < ps->performance_levels[i].mclk)
3069				mclk = ps->performance_levels[i].mclk;
3070		}
3071		for (i = 0; i < ps->performance_level_count; i++) {
3072			ps->performance_levels[i].mclk = mclk;
3073			ps->performance_levels[i].vddci = vddci;
3074		}
3075	} else {
3076		for (i = 1; i < ps->performance_level_count; i++) {
3077			if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk)
3078				ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk;
3079			if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci)
3080				ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci;
3081		}
3082	}
3083
3084	for (i = 0; i < ps->performance_level_count; i++)
3085		btc_adjust_clock_combinations(rdev, max_limits,
3086					      &ps->performance_levels[i]);
3087
3088	for (i = 0; i < ps->performance_level_count; i++) {
3089		if (ps->performance_levels[i].vddc < min_vce_voltage)
3090			ps->performance_levels[i].vddc = min_vce_voltage;
3091		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
3092						   ps->performance_levels[i].sclk,
3093						   max_limits->vddc,  &ps->performance_levels[i].vddc);
3094		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
3095						   ps->performance_levels[i].mclk,
3096						   max_limits->vddci, &ps->performance_levels[i].vddci);
3097		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
3098						   ps->performance_levels[i].mclk,
3099						   max_limits->vddc,  &ps->performance_levels[i].vddc);
3100		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
3101						   rdev->clock.current_dispclk,
3102						   max_limits->vddc,  &ps->performance_levels[i].vddc);
3103	}
3104
3105	for (i = 0; i < ps->performance_level_count; i++) {
3106		btc_apply_voltage_delta_rules(rdev,
3107					      max_limits->vddc, max_limits->vddci,
3108					      &ps->performance_levels[i].vddc,
3109					      &ps->performance_levels[i].vddci);
3110	}
3111
3112	ps->dc_compatible = true;
3113	for (i = 0; i < ps->performance_level_count; i++) {
3114		if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
3115			ps->dc_compatible = false;
3116	}
3117}
3118
3119#if 0
3120static int si_read_smc_soft_register(struct radeon_device *rdev,
3121				     u16 reg_offset, u32 *value)
3122{
3123	struct si_power_info *si_pi = si_get_pi(rdev);
3124
3125	return si_read_smc_sram_dword(rdev,
3126				      si_pi->soft_regs_start + reg_offset, value,
3127				      si_pi->sram_end);
3128}
3129#endif
3130
3131static int si_write_smc_soft_register(struct radeon_device *rdev,
3132				      u16 reg_offset, u32 value)
3133{
3134	struct si_power_info *si_pi = si_get_pi(rdev);
3135
3136	return si_write_smc_sram_dword(rdev,
3137				       si_pi->soft_regs_start + reg_offset,
3138				       value, si_pi->sram_end);
3139}
3140
3141static bool si_is_special_1gb_platform(struct radeon_device *rdev)
3142{
3143	bool ret = false;
3144	u32 tmp, width, row, column, bank, density;
3145	bool is_memory_gddr5, is_special;
3146
3147	tmp = RREG32(MC_SEQ_MISC0);
3148	is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE == ((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT));
3149	is_special = (MC_SEQ_MISC0_REV_ID_VALUE == ((tmp & MC_SEQ_MISC0_REV_ID_MASK) >> MC_SEQ_MISC0_REV_ID_SHIFT))
3150		& (MC_SEQ_MISC0_VEN_ID_VALUE == ((tmp & MC_SEQ_MISC0_VEN_ID_MASK) >> MC_SEQ_MISC0_VEN_ID_SHIFT));
3151
3152	WREG32(MC_SEQ_IO_DEBUG_INDEX, 0xb);
3153	width = ((RREG32(MC_SEQ_IO_DEBUG_DATA) >> 1) & 1) ? 16 : 32;
3154
3155	tmp = RREG32(MC_ARB_RAMCFG);
3156	row = ((tmp & NOOFROWS_MASK) >> NOOFROWS_SHIFT) + 10;
3157	column = ((tmp & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) + 8;
3158	bank = ((tmp & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + 2;
3159
3160	density = (1 << (row + column - 20 + bank)) * width;
3161
3162	if ((rdev->pdev->device == 0x6819) &&
3163	    is_memory_gddr5 && is_special && (density == 0x400))
3164		ret = true;
3165
3166	return ret;
3167}
3168
3169static void si_get_leakage_vddc(struct radeon_device *rdev)
3170{
3171	struct si_power_info *si_pi = si_get_pi(rdev);
3172	u16 vddc, count = 0;
3173	int i, ret;
3174
3175	for (i = 0; i < SISLANDS_MAX_LEAKAGE_COUNT; i++) {
3176		ret = radeon_atom_get_leakage_vddc_based_on_leakage_idx(rdev, &vddc, SISLANDS_LEAKAGE_INDEX0 + i);
3177
3178		if (!ret && (vddc > 0) && (vddc != (SISLANDS_LEAKAGE_INDEX0 + i))) {
3179			si_pi->leakage_voltage.entries[count].voltage = vddc;
3180			si_pi->leakage_voltage.entries[count].leakage_index =
3181				SISLANDS_LEAKAGE_INDEX0 + i;
3182			count++;
3183		}
3184	}
3185	si_pi->leakage_voltage.count = count;
3186}
3187
3188static int si_get_leakage_voltage_from_leakage_index(struct radeon_device *rdev,
3189						     u32 index, u16 *leakage_voltage)
3190{
3191	struct si_power_info *si_pi = si_get_pi(rdev);
3192	int i;
3193
3194	if (leakage_voltage == NULL)
3195		return -EINVAL;
3196
3197	if ((index & 0xff00) != 0xff00)
3198		return -EINVAL;
3199
3200	if ((index & 0xff) > SISLANDS_MAX_LEAKAGE_COUNT + 1)
3201		return -EINVAL;
3202
3203	if (index < SISLANDS_LEAKAGE_INDEX0)
3204		return -EINVAL;
3205
3206	for (i = 0; i < si_pi->leakage_voltage.count; i++) {
3207		if (si_pi->leakage_voltage.entries[i].leakage_index == index) {
3208			*leakage_voltage = si_pi->leakage_voltage.entries[i].voltage;
3209			return 0;
3210		}
3211	}
3212	return -EAGAIN;
3213}
3214
3215static void si_set_dpm_event_sources(struct radeon_device *rdev, u32 sources)
3216{
3217	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3218	bool want_thermal_protection;
3219	enum radeon_dpm_event_src dpm_event_src;
3220
3221	switch (sources) {
3222	case 0:
3223	default:
3224		want_thermal_protection = false;
3225		break;
3226	case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL):
3227		want_thermal_protection = true;
3228		dpm_event_src = RADEON_DPM_EVENT_SRC_DIGITAL;
3229		break;
3230	case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL):
3231		want_thermal_protection = true;
3232		dpm_event_src = RADEON_DPM_EVENT_SRC_EXTERNAL;
3233		break;
3234	case ((1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL) |
3235	      (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL)):
3236		want_thermal_protection = true;
3237		dpm_event_src = RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL;
3238		break;
3239	}
3240
3241	if (want_thermal_protection) {
3242		WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK);
3243		if (pi->thermal_protection)
3244			WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
3245	} else {
3246		WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
3247	}
3248}
3249
3250static void si_enable_auto_throttle_source(struct radeon_device *rdev,
3251					   enum radeon_dpm_auto_throttle_src source,
3252					   bool enable)
3253{
3254	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3255
3256	if (enable) {
3257		if (!(pi->active_auto_throttle_sources & (1 << source))) {
3258			pi->active_auto_throttle_sources |= 1 << source;
3259			si_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources);
3260		}
3261	} else {
3262		if (pi->active_auto_throttle_sources & (1 << source)) {
3263			pi->active_auto_throttle_sources &= ~(1 << source);
3264			si_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources);
3265		}
3266	}
3267}
3268
3269static void si_start_dpm(struct radeon_device *rdev)
3270{
3271	WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
3272}
3273
3274static void si_stop_dpm(struct radeon_device *rdev)
3275{
3276	WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
3277}
3278
3279static void si_enable_sclk_control(struct radeon_device *rdev, bool enable)
3280{
3281	if (enable)
3282		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
3283	else
3284		WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
3285
3286}
3287
3288#if 0
3289static int si_notify_hardware_of_thermal_state(struct radeon_device *rdev,
3290					       u32 thermal_level)
3291{
3292	PPSMC_Result ret;
3293
3294	if (thermal_level == 0) {
3295		ret = si_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
3296		if (ret == PPSMC_Result_OK)
3297			return 0;
3298		else
3299			return -EINVAL;
3300	}
3301	return 0;
3302}
3303
3304static void si_notify_hardware_vpu_recovery_event(struct radeon_device *rdev)
3305{
3306	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen, true);
3307}
3308#endif
3309
3310#if 0
3311static int si_notify_hw_of_powersource(struct radeon_device *rdev, bool ac_power)
3312{
3313	if (ac_power)
3314		return (si_send_msg_to_smc(rdev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ?
3315			0 : -EINVAL;
3316
3317	return 0;
3318}
3319#endif
3320
3321static PPSMC_Result si_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
3322						      PPSMC_Msg msg, u32 parameter)
3323{
3324	WREG32(SMC_SCRATCH0, parameter);
3325	return si_send_msg_to_smc(rdev, msg);
3326}
3327
3328static int si_restrict_performance_levels_before_switch(struct radeon_device *rdev)
3329{
3330	if (si_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
3331		return -EINVAL;
3332
3333	return (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ?
3334		0 : -EINVAL;
3335}
3336
3337int si_dpm_force_performance_level(struct radeon_device *rdev,
3338				   enum radeon_dpm_forced_level level)
3339{
3340	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
3341	struct ni_ps *ps = ni_get_ps(rps);
3342	u32 levels = ps->performance_level_count;
3343
3344	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
3345		if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
3346			return -EINVAL;
3347
3348		if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)
3349			return -EINVAL;
3350	} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
3351		if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
3352			return -EINVAL;
3353
3354		if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK)
3355			return -EINVAL;
3356	} else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
3357		if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
3358			return -EINVAL;
3359
3360		if (si_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
3361			return -EINVAL;
3362	}
3363
3364	rdev->pm.dpm.forced_level = level;
3365
3366	return 0;
3367}
3368
3369#if 0
3370static int si_set_boot_state(struct radeon_device *rdev)
3371{
3372	return (si_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ?
3373		0 : -EINVAL;
3374}
3375#endif
3376
3377static int si_set_sw_state(struct radeon_device *rdev)
3378{
3379	return (si_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ?
3380		0 : -EINVAL;
3381}
3382
3383static int si_halt_smc(struct radeon_device *rdev)
3384{
3385	if (si_send_msg_to_smc(rdev, PPSMC_MSG_Halt) != PPSMC_Result_OK)
3386		return -EINVAL;
3387
3388	return (si_wait_for_smc_inactive(rdev) == PPSMC_Result_OK) ?
3389		0 : -EINVAL;
3390}
3391
3392static int si_resume_smc(struct radeon_device *rdev)
3393{
3394	if (si_send_msg_to_smc(rdev, PPSMC_FlushDataCache) != PPSMC_Result_OK)
3395		return -EINVAL;
3396
3397	return (si_send_msg_to_smc(rdev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ?
3398		0 : -EINVAL;
3399}
3400
3401static void si_dpm_start_smc(struct radeon_device *rdev)
3402{
3403	si_program_jump_on_start(rdev);
3404	si_start_smc(rdev);
3405	si_start_smc_clock(rdev);
3406}
3407
3408static void si_dpm_stop_smc(struct radeon_device *rdev)
3409{
3410	si_reset_smc(rdev);
3411	si_stop_smc_clock(rdev);
3412}
3413
3414static int si_process_firmware_header(struct radeon_device *rdev)
3415{
3416	struct si_power_info *si_pi = si_get_pi(rdev);
3417	u32 tmp;
3418	int ret;
3419
3420	ret = si_read_smc_sram_dword(rdev,
3421				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3422				     SISLANDS_SMC_FIRMWARE_HEADER_stateTable,
3423				     &tmp, si_pi->sram_end);
3424	if (ret)
3425		return ret;
3426
3427	si_pi->state_table_start = tmp;
3428
3429	ret = si_read_smc_sram_dword(rdev,
3430				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3431				     SISLANDS_SMC_FIRMWARE_HEADER_softRegisters,
3432				     &tmp, si_pi->sram_end);
3433	if (ret)
3434		return ret;
3435
3436	si_pi->soft_regs_start = tmp;
3437
3438	ret = si_read_smc_sram_dword(rdev,
3439				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3440				     SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable,
3441				     &tmp, si_pi->sram_end);
3442	if (ret)
3443		return ret;
3444
3445	si_pi->mc_reg_table_start = tmp;
3446
3447	ret = si_read_smc_sram_dword(rdev,
3448				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3449				     SISLANDS_SMC_FIRMWARE_HEADER_fanTable,
3450				     &tmp, si_pi->sram_end);
3451	if (ret)
3452		return ret;
3453
3454	si_pi->fan_table_start = tmp;
3455
3456	ret = si_read_smc_sram_dword(rdev,
3457				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3458				     SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable,
3459				     &tmp, si_pi->sram_end);
3460	if (ret)
3461		return ret;
3462
3463	si_pi->arb_table_start = tmp;
3464
3465	ret = si_read_smc_sram_dword(rdev,
3466				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3467				     SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable,
3468				     &tmp, si_pi->sram_end);
3469	if (ret)
3470		return ret;
3471
3472	si_pi->cac_table_start = tmp;
3473
3474	ret = si_read_smc_sram_dword(rdev,
3475				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3476				     SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration,
3477				     &tmp, si_pi->sram_end);
3478	if (ret)
3479		return ret;
3480
3481	si_pi->dte_table_start = tmp;
3482
3483	ret = si_read_smc_sram_dword(rdev,
3484				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3485				     SISLANDS_SMC_FIRMWARE_HEADER_spllTable,
3486				     &tmp, si_pi->sram_end);
3487	if (ret)
3488		return ret;
3489
3490	si_pi->spll_table_start = tmp;
3491
3492	ret = si_read_smc_sram_dword(rdev,
3493				     SISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
3494				     SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters,
3495				     &tmp, si_pi->sram_end);
3496	if (ret)
3497		return ret;
3498
3499	si_pi->papm_cfg_table_start = tmp;
3500
3501	return ret;
3502}
3503
3504static void si_read_clock_registers(struct radeon_device *rdev)
3505{
3506	struct si_power_info *si_pi = si_get_pi(rdev);
3507
3508	si_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL);
3509	si_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2);
3510	si_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3);
3511	si_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4);
3512	si_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM);
3513	si_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
3514	si_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL);
3515	si_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL);
3516	si_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL);
3517	si_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL);
3518	si_pi->clock_registers.mpll_func_cntl = RREG32(MPLL_FUNC_CNTL);
3519	si_pi->clock_registers.mpll_func_cntl_1 = RREG32(MPLL_FUNC_CNTL_1);
3520	si_pi->clock_registers.mpll_func_cntl_2 = RREG32(MPLL_FUNC_CNTL_2);
3521	si_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1);
3522	si_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2);
3523}
3524
3525static void si_enable_thermal_protection(struct radeon_device *rdev,
3526					  bool enable)
3527{
3528	if (enable)
3529		WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
3530	else
3531		WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
3532}
3533
3534static void si_enable_acpi_power_management(struct radeon_device *rdev)
3535{
3536	WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN);
3537}
3538
3539#if 0
3540static int si_enter_ulp_state(struct radeon_device *rdev)
3541{
3542	WREG32(SMC_MESSAGE_0, PPSMC_MSG_SwitchToMinimumPower);
3543
3544	udelay(25000);
3545
3546	return 0;
3547}
3548
3549static int si_exit_ulp_state(struct radeon_device *rdev)
3550{
3551	int i;
3552
3553	WREG32(SMC_MESSAGE_0, PPSMC_MSG_ResumeFromMinimumPower);
3554
3555	udelay(7000);
3556
3557	for (i = 0; i < rdev->usec_timeout; i++) {
3558		if (RREG32(SMC_RESP_0) == 1)
3559			break;
3560		udelay(1000);
3561	}
3562
3563	return 0;
3564}
3565#endif
3566
3567static int si_notify_smc_display_change(struct radeon_device *rdev,
3568				     bool has_display)
3569{
3570	PPSMC_Msg msg = has_display ?
3571		PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay;
3572
3573	return (si_send_msg_to_smc(rdev, msg) == PPSMC_Result_OK) ?
3574		0 : -EINVAL;
3575}
3576
3577static void si_program_response_times(struct radeon_device *rdev)
3578{
3579	u32 voltage_response_time, acpi_delay_time, vbi_time_out;
3580	u32 vddc_dly, acpi_dly, vbi_dly;
3581	u32 reference_clock;
3582
3583	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_mvdd_chg_time, 1);
3584
3585	voltage_response_time = (u32)rdev->pm.dpm.voltage_response_time;
3586
3587	if (voltage_response_time == 0)
3588		voltage_response_time = 1000;
3589
3590	acpi_delay_time = 15000;
3591	vbi_time_out = 100000;
3592
3593	reference_clock = radeon_get_xclk(rdev);
3594
3595	vddc_dly = (voltage_response_time  * reference_clock) / 100;
3596	acpi_dly = (acpi_delay_time * reference_clock) / 100;
3597	vbi_dly  = (vbi_time_out * reference_clock) / 100;
3598
3599	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_delay_vreg,  vddc_dly);
3600	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_delay_acpi,  acpi_dly);
3601	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);
3602	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA);
3603}
3604
3605static void si_program_ds_registers(struct radeon_device *rdev)
3606{
3607	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
3608	u32 tmp = 1; /* XXX: 0x10 on tahiti A0 */
3609
3610	if (eg_pi->sclk_deep_sleep) {
3611		WREG32_P(MISC_CLK_CNTL, DEEP_SLEEP_CLK_SEL(tmp), ~DEEP_SLEEP_CLK_SEL_MASK);
3612		WREG32_P(CG_SPLL_AUTOSCALE_CNTL, AUTOSCALE_ON_SS_CLEAR,
3613			 ~AUTOSCALE_ON_SS_CLEAR);
3614	}
3615}
3616
3617static void si_program_display_gap(struct radeon_device *rdev)
3618{
3619	u32 tmp, pipe;
3620	int i;
3621
3622	tmp = RREG32(CG_DISPLAY_GAP_CNTL) & ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
3623	if (rdev->pm.dpm.new_active_crtc_count > 0)
3624		tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
3625	else
3626		tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE);
3627
3628	if (rdev->pm.dpm.new_active_crtc_count > 1)
3629		tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
3630	else
3631		tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE);
3632
3633	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
3634
3635	tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG);
3636	pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT;
3637
3638	if ((rdev->pm.dpm.new_active_crtc_count > 0) &&
3639	    (!(rdev->pm.dpm.new_active_crtcs & (1 << pipe)))) {
3640		/* find the first active crtc */
3641		for (i = 0; i < rdev->num_crtc; i++) {
3642			if (rdev->pm.dpm.new_active_crtcs & (1 << i))
3643				break;
3644		}
3645		if (i == rdev->num_crtc)
3646			pipe = 0;
3647		else
3648			pipe = i;
3649
3650		tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK;
3651		tmp |= DCCG_DISP1_SLOW_SELECT(pipe);
3652		WREG32(DCCG_DISP_SLOW_SELECT_REG, tmp);
3653	}
3654
3655	/* Setting this to false forces the performance state to low if the crtcs are disabled.
3656	 * This can be a problem on PowerXpress systems or if you want to use the card
3657	 * for offscreen rendering or compute if there are no crtcs enabled.
3658	 */
3659	si_notify_smc_display_change(rdev, rdev->pm.dpm.new_active_crtc_count > 0);
3660}
3661
3662static void si_enable_spread_spectrum(struct radeon_device *rdev, bool enable)
3663{
3664	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3665
3666	if (enable) {
3667		if (pi->sclk_ss)
3668			WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN);
3669	} else {
3670		WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN);
3671		WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN);
3672	}
3673}
3674
3675static void si_setup_bsp(struct radeon_device *rdev)
3676{
3677	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3678	u32 xclk = radeon_get_xclk(rdev);
3679
3680	r600_calculate_u_and_p(pi->asi,
3681			       xclk,
3682			       16,
3683			       &pi->bsp,
3684			       &pi->bsu);
3685
3686	r600_calculate_u_and_p(pi->pasi,
3687			       xclk,
3688			       16,
3689			       &pi->pbsp,
3690			       &pi->pbsu);
3691
3692
3693	pi->dsp = BSP(pi->bsp) | BSU(pi->bsu);
3694	pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu);
3695
3696	WREG32(CG_BSP, pi->dsp);
3697}
3698
3699static void si_program_git(struct radeon_device *rdev)
3700{
3701	WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK);
3702}
3703
3704static void si_program_tp(struct radeon_device *rdev)
3705{
3706	int i;
3707	enum r600_td td = R600_TD_DFLT;
3708
3709	for (i = 0; i < R600_PM_NUMBER_OF_TC; i++)
3710		WREG32(CG_FFCT_0 + (i * 4), (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i])));
3711
3712	if (td == R600_TD_AUTO)
3713		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL);
3714	else
3715		WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL);
3716
3717	if (td == R600_TD_UP)
3718		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE);
3719
3720	if (td == R600_TD_DOWN)
3721		WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);
3722}
3723
3724static void si_program_tpp(struct radeon_device *rdev)
3725{
3726	WREG32(CG_TPC, R600_TPC_DFLT);
3727}
3728
3729static void si_program_sstp(struct radeon_device *rdev)
3730{
3731	WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT)));
3732}
3733
3734static void si_enable_display_gap(struct radeon_device *rdev)
3735{
3736	u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
3737
3738	tmp &= ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
3739	tmp |= (DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE) |
3740		DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE));
3741
3742	tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
3743	tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK) |
3744		DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE));
3745	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
3746}
3747
3748static void si_program_vc(struct radeon_device *rdev)
3749{
3750	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3751
3752	WREG32(CG_FTV, pi->vrc);
3753}
3754
3755static void si_clear_vc(struct radeon_device *rdev)
3756{
3757	WREG32(CG_FTV, 0);
3758}
3759
3760u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock)
3761{
3762	u8 mc_para_index;
3763
3764	if (memory_clock < 10000)
3765		mc_para_index = 0;
3766	else if (memory_clock >= 80000)
3767		mc_para_index = 0x0f;
3768	else
3769		mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1);
3770	return mc_para_index;
3771}
3772
3773u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode)
3774{
3775	u8 mc_para_index;
3776
3777	if (strobe_mode) {
3778		if (memory_clock < 12500)
3779			mc_para_index = 0x00;
3780		else if (memory_clock > 47500)
3781			mc_para_index = 0x0f;
3782		else
3783			mc_para_index = (u8)((memory_clock - 10000) / 2500);
3784	} else {
3785		if (memory_clock < 65000)
3786			mc_para_index = 0x00;
3787		else if (memory_clock > 135000)
3788			mc_para_index = 0x0f;
3789		else
3790			mc_para_index = (u8)((memory_clock - 60000) / 5000);
3791	}
3792	return mc_para_index;
3793}
3794
3795static u8 si_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
3796{
3797	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3798	bool strobe_mode = false;
3799	u8 result = 0;
3800
3801	if (mclk <= pi->mclk_strobe_mode_threshold)
3802		strobe_mode = true;
3803
3804	if (pi->mem_gddr5)
3805		result = si_get_mclk_frequency_ratio(mclk, strobe_mode);
3806	else
3807		result = si_get_ddr3_mclk_frequency_ratio(mclk);
3808
3809	if (strobe_mode)
3810		result |= SISLANDS_SMC_STROBE_ENABLE;
3811
3812	return result;
3813}
3814
3815static int si_upload_firmware(struct radeon_device *rdev)
3816{
3817	struct si_power_info *si_pi = si_get_pi(rdev);
3818	int ret;
3819
3820	si_reset_smc(rdev);
3821	si_stop_smc_clock(rdev);
3822
3823	ret = si_load_smc_ucode(rdev, si_pi->sram_end);
3824
3825	return ret;
3826}
3827
3828static bool si_validate_phase_shedding_tables(struct radeon_device *rdev,
3829					      const struct atom_voltage_table *table,
3830					      const struct radeon_phase_shedding_limits_table *limits)
3831{
3832	u32 data, num_bits, num_levels;
3833
3834	if ((table == NULL) || (limits == NULL))
3835		return false;
3836
3837	data = table->mask_low;
3838
3839	num_bits = hweight32(data);
3840
3841	if (num_bits == 0)
3842		return false;
3843
3844	num_levels = (1 << num_bits);
3845
3846	if (table->count != num_levels)
3847		return false;
3848
3849	if (limits->count != (num_levels - 1))
3850		return false;
3851
3852	return true;
3853}
3854
3855void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
3856					      u32 max_voltage_steps,
3857					      struct atom_voltage_table *voltage_table)
3858{
3859	unsigned int i, diff;
3860
3861	if (voltage_table->count <= max_voltage_steps)
3862		return;
3863
3864	diff = voltage_table->count - max_voltage_steps;
3865
3866	for (i= 0; i < max_voltage_steps; i++)
3867		voltage_table->entries[i] = voltage_table->entries[i + diff];
3868
3869	voltage_table->count = max_voltage_steps;
3870}
3871
3872static int si_get_svi2_voltage_table(struct radeon_device *rdev,
3873				     struct radeon_clock_voltage_dependency_table *voltage_dependency_table,
3874				     struct atom_voltage_table *voltage_table)
3875{
3876	u32 i;
3877
3878	if (voltage_dependency_table == NULL)
3879		return -EINVAL;
3880
3881	voltage_table->mask_low = 0;
3882	voltage_table->phase_delay = 0;
3883
3884	voltage_table->count = voltage_dependency_table->count;
3885	for (i = 0; i < voltage_table->count; i++) {
3886		voltage_table->entries[i].value = voltage_dependency_table->entries[i].v;
3887		voltage_table->entries[i].smio_low = 0;
3888	}
3889
3890	return 0;
3891}
3892
3893static int si_construct_voltage_tables(struct radeon_device *rdev)
3894{
3895	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3896	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
3897	struct si_power_info *si_pi = si_get_pi(rdev);
3898	int ret;
3899
3900	if (pi->voltage_control) {
3901		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
3902						    VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table);
3903		if (ret)
3904			return ret;
3905
3906		if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
3907			si_trim_voltage_table_to_fit_state_table(rdev,
3908								 SISLANDS_MAX_NO_VREG_STEPS,
3909								 &eg_pi->vddc_voltage_table);
3910	} else if (si_pi->voltage_control_svi2) {
3911		ret = si_get_svi2_voltage_table(rdev,
3912						&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
3913						&eg_pi->vddc_voltage_table);
3914		if (ret)
3915			return ret;
3916	} else {
3917		return -EINVAL;
3918	}
3919
3920	if (eg_pi->vddci_control) {
3921		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDCI,
3922						    VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddci_voltage_table);
3923		if (ret)
3924			return ret;
3925
3926		if (eg_pi->vddci_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
3927			si_trim_voltage_table_to_fit_state_table(rdev,
3928								 SISLANDS_MAX_NO_VREG_STEPS,
3929								 &eg_pi->vddci_voltage_table);
3930	}
3931	if (si_pi->vddci_control_svi2) {
3932		ret = si_get_svi2_voltage_table(rdev,
3933						&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
3934						&eg_pi->vddci_voltage_table);
3935		if (ret)
3936			return ret;
3937	}
3938
3939	if (pi->mvdd_control) {
3940		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_MVDDC,
3941						    VOLTAGE_OBJ_GPIO_LUT, &si_pi->mvdd_voltage_table);
3942
3943		if (ret) {
3944			pi->mvdd_control = false;
3945			return ret;
3946		}
3947
3948		if (si_pi->mvdd_voltage_table.count == 0) {
3949			pi->mvdd_control = false;
3950			return -EINVAL;
3951		}
3952
3953		if (si_pi->mvdd_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS)
3954			si_trim_voltage_table_to_fit_state_table(rdev,
3955								 SISLANDS_MAX_NO_VREG_STEPS,
3956								 &si_pi->mvdd_voltage_table);
3957	}
3958
3959	if (si_pi->vddc_phase_shed_control) {
3960		ret = radeon_atom_get_voltage_table(rdev, VOLTAGE_TYPE_VDDC,
3961						    VOLTAGE_OBJ_PHASE_LUT, &si_pi->vddc_phase_shed_table);
3962		if (ret)
3963			si_pi->vddc_phase_shed_control = false;
3964
3965		if ((si_pi->vddc_phase_shed_table.count == 0) ||
3966		    (si_pi->vddc_phase_shed_table.count > SISLANDS_MAX_NO_VREG_STEPS))
3967			si_pi->vddc_phase_shed_control = false;
3968	}
3969
3970	return 0;
3971}
3972
3973static void si_populate_smc_voltage_table(struct radeon_device *rdev,
3974					  const struct atom_voltage_table *voltage_table,
3975					  SISLANDS_SMC_STATETABLE *table)
3976{
3977	unsigned int i;
3978
3979	for (i = 0; i < voltage_table->count; i++)
3980		table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low);
3981}
3982
3983static int si_populate_smc_voltage_tables(struct radeon_device *rdev,
3984					  SISLANDS_SMC_STATETABLE *table)
3985{
3986	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
3987	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
3988	struct si_power_info *si_pi = si_get_pi(rdev);
3989	u8 i;
3990
3991	if (si_pi->voltage_control_svi2) {
3992		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc,
3993			si_pi->svc_gpio_id);
3994		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd,
3995			si_pi->svd_gpio_id);
3996		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type,
3997					   2);
3998	} else {
3999		if (eg_pi->vddc_voltage_table.count) {
4000			si_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
4001			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] =
4002				cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
4003
4004			for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
4005				if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
4006					table->maxVDDCIndexInPPTable = i;
4007					break;
4008				}
4009			}
4010		}
4011
4012		if (eg_pi->vddci_voltage_table.count) {
4013			si_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
4014
4015			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] =
4016				cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
4017		}
4018
4019
4020		if (si_pi->mvdd_voltage_table.count) {
4021			si_populate_smc_voltage_table(rdev, &si_pi->mvdd_voltage_table, table);
4022
4023			table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] =
4024				cpu_to_be32(si_pi->mvdd_voltage_table.mask_low);
4025		}
4026
4027		if (si_pi->vddc_phase_shed_control) {
4028			if (si_validate_phase_shedding_tables(rdev, &si_pi->vddc_phase_shed_table,
4029							      &rdev->pm.dpm.dyn_state.phase_shedding_limits_table)) {
4030				si_populate_smc_voltage_table(rdev, &si_pi->vddc_phase_shed_table, table);
4031
4032				table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING] =
4033					cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low);
4034
4035				si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_phase_shedding_delay,
4036							   (u32)si_pi->vddc_phase_shed_table.phase_delay);
4037			} else {
4038				si_pi->vddc_phase_shed_control = false;
4039			}
4040		}
4041	}
4042
4043	return 0;
4044}
4045
4046static int si_populate_voltage_value(struct radeon_device *rdev,
4047				     const struct atom_voltage_table *table,
4048				     u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage)
4049{
4050	unsigned int i;
4051
4052	for (i = 0; i < table->count; i++) {
4053		if (value <= table->entries[i].value) {
4054			voltage->index = (u8)i;
4055			voltage->value = cpu_to_be16(table->entries[i].value);
4056			break;
4057		}
4058	}
4059
4060	if (i >= table->count)
4061		return -EINVAL;
4062
4063	return 0;
4064}
4065
4066static int si_populate_mvdd_value(struct radeon_device *rdev, u32 mclk,
4067				  SISLANDS_SMC_VOLTAGE_VALUE *voltage)
4068{
4069	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4070	struct si_power_info *si_pi = si_get_pi(rdev);
4071
4072	if (pi->mvdd_control) {
4073		if (mclk <= pi->mvdd_split_frequency)
4074			voltage->index = 0;
4075		else
4076			voltage->index = (u8)(si_pi->mvdd_voltage_table.count) - 1;
4077
4078		voltage->value = cpu_to_be16(si_pi->mvdd_voltage_table.entries[voltage->index].value);
4079	}
4080	return 0;
4081}
4082
4083static int si_get_std_voltage_value(struct radeon_device *rdev,
4084				    SISLANDS_SMC_VOLTAGE_VALUE *voltage,
4085				    u16 *std_voltage)
4086{
4087	u16 v_index;
4088	bool voltage_found = false;
4089	*std_voltage = be16_to_cpu(voltage->value);
4090
4091	if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries) {
4092		if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE) {
4093			if (rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries == NULL)
4094				return -EINVAL;
4095
4096			for (v_index = 0; (u32)v_index < rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {
4097				if (be16_to_cpu(voltage->value) ==
4098				    (u16)rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {
4099					voltage_found = true;
4100					if ((u32)v_index < rdev->pm.dpm.dyn_state.cac_leakage_table.count)
4101						*std_voltage =
4102							rdev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc;
4103					else
4104						*std_voltage =
4105							rdev->pm.dpm.dyn_state.cac_leakage_table.entries[rdev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc;
4106					break;
4107				}
4108			}
4109
4110			if (!voltage_found) {
4111				for (v_index = 0; (u32)v_index < rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) {
4112					if (be16_to_cpu(voltage->value) <=
4113					    (u16)rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) {
4114						voltage_found = true;
4115						if ((u32)v_index < rdev->pm.dpm.dyn_state.cac_leakage_table.count)
4116							*std_voltage =
4117								rdev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc;
4118						else
4119							*std_voltage =
4120								rdev->pm.dpm.dyn_state.cac_leakage_table.entries[rdev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc;
4121						break;
4122					}
4123				}
4124			}
4125		} else {
4126			if ((u32)voltage->index < rdev->pm.dpm.dyn_state.cac_leakage_table.count)
4127				*std_voltage = rdev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc;
4128		}
4129	}
4130
4131	return 0;
4132}
4133
4134static int si_populate_std_voltage_value(struct radeon_device *rdev,
4135					 u16 value, u8 index,
4136					 SISLANDS_SMC_VOLTAGE_VALUE *voltage)
4137{
4138	voltage->index = index;
4139	voltage->value = cpu_to_be16(value);
4140
4141	return 0;
4142}
4143
4144static int si_populate_phase_shedding_value(struct radeon_device *rdev,
4145					    const struct radeon_phase_shedding_limits_table *limits,
4146					    u16 voltage, u32 sclk, u32 mclk,
4147					    SISLANDS_SMC_VOLTAGE_VALUE *smc_voltage)
4148{
4149	unsigned int i;
4150
4151	for (i = 0; i < limits->count; i++) {
4152		if ((voltage <= limits->entries[i].voltage) &&
4153		    (sclk <= limits->entries[i].sclk) &&
4154		    (mclk <= limits->entries[i].mclk))
4155			break;
4156	}
4157
4158	smc_voltage->phase_settings = (u8)i;
4159
4160	return 0;
4161}
4162
4163static int si_init_arb_table_index(struct radeon_device *rdev)
4164{
4165	struct si_power_info *si_pi = si_get_pi(rdev);
4166	u32 tmp;
4167	int ret;
4168
4169	ret = si_read_smc_sram_dword(rdev, si_pi->arb_table_start, &tmp, si_pi->sram_end);
4170	if (ret)
4171		return ret;
4172
4173	tmp &= 0x00FFFFFF;
4174	tmp |= MC_CG_ARB_FREQ_F1 << 24;
4175
4176	return si_write_smc_sram_dword(rdev, si_pi->arb_table_start,  tmp, si_pi->sram_end);
4177}
4178
4179static int si_initial_switch_from_arb_f0_to_f1(struct radeon_device *rdev)
4180{
4181	return ni_copy_and_switch_arb_sets(rdev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
4182}
4183
4184static int si_reset_to_default(struct radeon_device *rdev)
4185{
4186	return (si_send_msg_to_smc(rdev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ?
4187		0 : -EINVAL;
4188}
4189
4190static int si_force_switch_to_arb_f0(struct radeon_device *rdev)
4191{
4192	struct si_power_info *si_pi = si_get_pi(rdev);
4193	u32 tmp;
4194	int ret;
4195
4196	ret = si_read_smc_sram_dword(rdev, si_pi->arb_table_start,
4197				     &tmp, si_pi->sram_end);
4198	if (ret)
4199		return ret;
4200
4201	tmp = (tmp >> 24) & 0xff;
4202
4203	if (tmp == MC_CG_ARB_FREQ_F0)
4204		return 0;
4205
4206	return ni_copy_and_switch_arb_sets(rdev, tmp, MC_CG_ARB_FREQ_F0);
4207}
4208
4209static u32 si_calculate_memory_refresh_rate(struct radeon_device *rdev,
4210					    u32 engine_clock)
4211{
4212	u32 dram_rows;
4213	u32 dram_refresh_rate;
4214	u32 mc_arb_rfsh_rate;
4215	u32 tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
4216
4217	if (tmp >= 4)
4218		dram_rows = 16384;
4219	else
4220		dram_rows = 1 << (tmp + 10);
4221
4222	dram_refresh_rate = 1 << ((RREG32(MC_SEQ_MISC0) & 0x3) + 3);
4223	mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64;
4224
4225	return mc_arb_rfsh_rate;
4226}
4227
4228static int si_populate_memory_timing_parameters(struct radeon_device *rdev,
4229						struct rv7xx_pl *pl,
4230						SMC_SIslands_MCArbDramTimingRegisterSet *arb_regs)
4231{
4232	u32 dram_timing;
4233	u32 dram_timing2;
4234	u32 burst_time;
4235
4236	arb_regs->mc_arb_rfsh_rate =
4237		(u8)si_calculate_memory_refresh_rate(rdev, pl->sclk);
4238
4239	radeon_atom_set_engine_dram_timings(rdev,
4240					    pl->sclk,
4241					    pl->mclk);
4242
4243	dram_timing  = RREG32(MC_ARB_DRAM_TIMING);
4244	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
4245	burst_time = RREG32(MC_ARB_BURST_TIME) & STATE0_MASK;
4246
4247	arb_regs->mc_arb_dram_timing  = cpu_to_be32(dram_timing);
4248	arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2);
4249	arb_regs->mc_arb_burst_time = (u8)burst_time;
4250
4251	return 0;
4252}
4253
4254static int si_do_program_memory_timing_parameters(struct radeon_device *rdev,
4255						  struct radeon_ps *radeon_state,
4256						  unsigned int first_arb_set)
4257{
4258	struct si_power_info *si_pi = si_get_pi(rdev);
4259	struct ni_ps *state = ni_get_ps(radeon_state);
4260	SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };
4261	int i, ret = 0;
4262
4263	for (i = 0; i < state->performance_level_count; i++) {
4264		ret = si_populate_memory_timing_parameters(rdev, &state->performance_levels[i], &arb_regs);
4265		if (ret)
4266			break;
4267		ret = si_copy_bytes_to_smc(rdev,
4268					   si_pi->arb_table_start +
4269					   offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) +
4270					   sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i),
4271					   (u8 *)&arb_regs,
4272					   sizeof(SMC_SIslands_MCArbDramTimingRegisterSet),
4273					   si_pi->sram_end);
4274		if (ret)
4275			break;
4276	}
4277
4278	return ret;
4279}
4280
4281static int si_program_memory_timing_parameters(struct radeon_device *rdev,
4282					       struct radeon_ps *radeon_new_state)
4283{
4284	return si_do_program_memory_timing_parameters(rdev, radeon_new_state,
4285						      SISLANDS_DRIVER_STATE_ARB_INDEX);
4286}
4287
4288static int si_populate_initial_mvdd_value(struct radeon_device *rdev,
4289					  struct SISLANDS_SMC_VOLTAGE_VALUE *voltage)
4290{
4291	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4292	struct si_power_info *si_pi = si_get_pi(rdev);
4293
4294	if (pi->mvdd_control)
4295		return si_populate_voltage_value(rdev, &si_pi->mvdd_voltage_table,
4296						 si_pi->mvdd_bootup_value, voltage);
4297
4298	return 0;
4299}
4300
4301static int si_populate_smc_initial_state(struct radeon_device *rdev,
4302					 struct radeon_ps *radeon_initial_state,
4303					 SISLANDS_SMC_STATETABLE *table)
4304{
4305	struct ni_ps *initial_state = ni_get_ps(radeon_initial_state);
4306	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4307	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
4308	struct si_power_info *si_pi = si_get_pi(rdev);
4309	u32 reg;
4310	int ret;
4311
4312	table->initialState.level.mclk.vDLL_CNTL =
4313		cpu_to_be32(si_pi->clock_registers.dll_cntl);
4314	table->initialState.level.mclk.vMCLK_PWRMGT_CNTL =
4315		cpu_to_be32(si_pi->clock_registers.mclk_pwrmgt_cntl);
4316	table->initialState.level.mclk.vMPLL_AD_FUNC_CNTL =
4317		cpu_to_be32(si_pi->clock_registers.mpll_ad_func_cntl);
4318	table->initialState.level.mclk.vMPLL_DQ_FUNC_CNTL =
4319		cpu_to_be32(si_pi->clock_registers.mpll_dq_func_cntl);
4320	table->initialState.level.mclk.vMPLL_FUNC_CNTL =
4321		cpu_to_be32(si_pi->clock_registers.mpll_func_cntl);
4322	table->initialState.level.mclk.vMPLL_FUNC_CNTL_1 =
4323		cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_1);
4324	table->initialState.level.mclk.vMPLL_FUNC_CNTL_2 =
4325		cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_2);
4326	table->initialState.level.mclk.vMPLL_SS =
4327		cpu_to_be32(si_pi->clock_registers.mpll_ss1);
4328	table->initialState.level.mclk.vMPLL_SS2 =
4329		cpu_to_be32(si_pi->clock_registers.mpll_ss2);
4330
4331	table->initialState.level.mclk.mclk_value =
4332		cpu_to_be32(initial_state->performance_levels[0].mclk);
4333
4334	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL =
4335		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl);
4336	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_2 =
4337		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_2);
4338	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_3 =
4339		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_3);
4340	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_4 =
4341		cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_4);
4342	table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM =
4343		cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum);
4344	table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM_2  =
4345		cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum_2);
4346
4347	table->initialState.level.sclk.sclk_value =
4348		cpu_to_be32(initial_state->performance_levels[0].sclk);
4349
4350	table->initialState.level.arbRefreshState =
4351		SISLANDS_INITIAL_STATE_ARB_INDEX;
4352
4353	table->initialState.level.ACIndex = 0;
4354
4355	ret = si_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
4356					initial_state->performance_levels[0].vddc,
4357					&table->initialState.level.vddc);
4358
4359	if (!ret) {
4360		u16 std_vddc;
4361
4362		ret = si_get_std_voltage_value(rdev,
4363					       &table->initialState.level.vddc,
4364					       &std_vddc);
4365		if (!ret)
4366			si_populate_std_voltage_value(rdev, std_vddc,
4367						      table->initialState.level.vddc.index,
4368						      &table->initialState.level.std_vddc);
4369	}
4370
4371	if (eg_pi->vddci_control)
4372		si_populate_voltage_value(rdev,
4373					  &eg_pi->vddci_voltage_table,
4374					  initial_state->performance_levels[0].vddci,
4375					  &table->initialState.level.vddci);
4376
4377	if (si_pi->vddc_phase_shed_control)
4378		si_populate_phase_shedding_value(rdev,
4379						 &rdev->pm.dpm.dyn_state.phase_shedding_limits_table,
4380						 initial_state->performance_levels[0].vddc,
4381						 initial_state->performance_levels[0].sclk,
4382						 initial_state->performance_levels[0].mclk,
4383						 &table->initialState.level.vddc);
4384
4385	si_populate_initial_mvdd_value(rdev, &table->initialState.level.mvdd);
4386
4387	reg = CG_R(0xffff) | CG_L(0);
4388	table->initialState.level.aT = cpu_to_be32(reg);
4389
4390	table->initialState.level.bSP = cpu_to_be32(pi->dsp);
4391
4392	table->initialState.level.gen2PCIE = (u8)si_pi->boot_pcie_gen;
4393
4394	if (pi->mem_gddr5) {
4395		table->initialState.level.strobeMode =
4396			si_get_strobe_mode_settings(rdev,
4397						    initial_state->performance_levels[0].mclk);
4398
4399		if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold)
4400			table->initialState.level.mcFlags = SISLANDS_SMC_MC_EDC_RD_FLAG | SISLANDS_SMC_MC_EDC_WR_FLAG;
4401		else
4402			table->initialState.level.mcFlags =  0;
4403	}
4404
4405	table->initialState.levelCount = 1;
4406
4407	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
4408
4409	table->initialState.level.dpm2.MaxPS = 0;
4410	table->initialState.level.dpm2.NearTDPDec = 0;
4411	table->initialState.level.dpm2.AboveSafeInc = 0;
4412	table->initialState.level.dpm2.BelowSafeInc = 0;
4413	table->initialState.level.dpm2.PwrEfficiencyRatio = 0;
4414
4415	reg = MIN_POWER_MASK | MAX_POWER_MASK;
4416	table->initialState.level.SQPowerThrottle = cpu_to_be32(reg);
4417
4418	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
4419	table->initialState.level.SQPowerThrottle_2 = cpu_to_be32(reg);
4420
4421	return 0;
4422}
4423
4424static int si_populate_smc_acpi_state(struct radeon_device *rdev,
4425				      SISLANDS_SMC_STATETABLE *table)
4426{
4427	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4428	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
4429	struct si_power_info *si_pi = si_get_pi(rdev);
4430	u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl;
4431	u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2;
4432	u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3;
4433	u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4;
4434	u32 dll_cntl = si_pi->clock_registers.dll_cntl;
4435	u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl;
4436	u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl;
4437	u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl;
4438	u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl;
4439	u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1;
4440	u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2;
4441	u32 reg;
4442	int ret;
4443
4444	table->ACPIState = table->initialState;
4445
4446	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
4447
4448	if (pi->acpi_vddc) {
4449		ret = si_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
4450						pi->acpi_vddc, &table->ACPIState.level.vddc);
4451		if (!ret) {
4452			u16 std_vddc;
4453
4454			ret = si_get_std_voltage_value(rdev,
4455						       &table->ACPIState.level.vddc, &std_vddc);
4456			if (!ret)
4457				si_populate_std_voltage_value(rdev, std_vddc,
4458							      table->ACPIState.level.vddc.index,
4459							      &table->ACPIState.level.std_vddc);
4460		}
4461		table->ACPIState.level.gen2PCIE = si_pi->acpi_pcie_gen;
4462
4463		if (si_pi->vddc_phase_shed_control) {
4464			si_populate_phase_shedding_value(rdev,
4465							 &rdev->pm.dpm.dyn_state.phase_shedding_limits_table,
4466							 pi->acpi_vddc,
4467							 0,
4468							 0,
4469							 &table->ACPIState.level.vddc);
4470		}
4471	} else {
4472		ret = si_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
4473						pi->min_vddc_in_table, &table->ACPIState.level.vddc);
4474		if (!ret) {
4475			u16 std_vddc;
4476
4477			ret = si_get_std_voltage_value(rdev,
4478						       &table->ACPIState.level.vddc, &std_vddc);
4479
4480			if (!ret)
4481				si_populate_std_voltage_value(rdev, std_vddc,
4482							      table->ACPIState.level.vddc.index,
4483							      &table->ACPIState.level.std_vddc);
4484		}
4485		table->ACPIState.level.gen2PCIE = (u8)r600_get_pcie_gen_support(rdev,
4486										    si_pi->sys_pcie_mask,
4487										    si_pi->boot_pcie_gen,
4488										    RADEON_PCIE_GEN1);
4489
4490		if (si_pi->vddc_phase_shed_control)
4491			si_populate_phase_shedding_value(rdev,
4492							 &rdev->pm.dpm.dyn_state.phase_shedding_limits_table,
4493							 pi->min_vddc_in_table,
4494							 0,
4495							 0,
4496							 &table->ACPIState.level.vddc);
4497	}
4498
4499	if (pi->acpi_vddc) {
4500		if (eg_pi->acpi_vddci)
4501			si_populate_voltage_value(rdev, &eg_pi->vddci_voltage_table,
4502						  eg_pi->acpi_vddci,
4503						  &table->ACPIState.level.vddci);
4504	}
4505
4506	mclk_pwrmgt_cntl |= MRDCK0_RESET | MRDCK1_RESET;
4507	mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB);
4508
4509	dll_cntl &= ~(MRDCK0_BYPASS | MRDCK1_BYPASS);
4510
4511	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
4512	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
4513
4514	table->ACPIState.level.mclk.vDLL_CNTL =
4515		cpu_to_be32(dll_cntl);
4516	table->ACPIState.level.mclk.vMCLK_PWRMGT_CNTL =
4517		cpu_to_be32(mclk_pwrmgt_cntl);
4518	table->ACPIState.level.mclk.vMPLL_AD_FUNC_CNTL =
4519		cpu_to_be32(mpll_ad_func_cntl);
4520	table->ACPIState.level.mclk.vMPLL_DQ_FUNC_CNTL =
4521		cpu_to_be32(mpll_dq_func_cntl);
4522	table->ACPIState.level.mclk.vMPLL_FUNC_CNTL =
4523		cpu_to_be32(mpll_func_cntl);
4524	table->ACPIState.level.mclk.vMPLL_FUNC_CNTL_1 =
4525		cpu_to_be32(mpll_func_cntl_1);
4526	table->ACPIState.level.mclk.vMPLL_FUNC_CNTL_2 =
4527		cpu_to_be32(mpll_func_cntl_2);
4528	table->ACPIState.level.mclk.vMPLL_SS =
4529		cpu_to_be32(si_pi->clock_registers.mpll_ss1);
4530	table->ACPIState.level.mclk.vMPLL_SS2 =
4531		cpu_to_be32(si_pi->clock_registers.mpll_ss2);
4532
4533	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL =
4534		cpu_to_be32(spll_func_cntl);
4535	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_2 =
4536		cpu_to_be32(spll_func_cntl_2);
4537	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_3 =
4538		cpu_to_be32(spll_func_cntl_3);
4539	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_4 =
4540		cpu_to_be32(spll_func_cntl_4);
4541
4542	table->ACPIState.level.mclk.mclk_value = 0;
4543	table->ACPIState.level.sclk.sclk_value = 0;
4544
4545	si_populate_mvdd_value(rdev, 0, &table->ACPIState.level.mvdd);
4546
4547	if (eg_pi->dynamic_ac_timing)
4548		table->ACPIState.level.ACIndex = 0;
4549
4550	table->ACPIState.level.dpm2.MaxPS = 0;
4551	table->ACPIState.level.dpm2.NearTDPDec = 0;
4552	table->ACPIState.level.dpm2.AboveSafeInc = 0;
4553	table->ACPIState.level.dpm2.BelowSafeInc = 0;
4554	table->ACPIState.level.dpm2.PwrEfficiencyRatio = 0;
4555
4556	reg = MIN_POWER_MASK | MAX_POWER_MASK;
4557	table->ACPIState.level.SQPowerThrottle = cpu_to_be32(reg);
4558
4559	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
4560	table->ACPIState.level.SQPowerThrottle_2 = cpu_to_be32(reg);
4561
4562	return 0;
4563}
4564
4565static int si_populate_ulv_state(struct radeon_device *rdev,
4566				 struct SISLANDS_SMC_SWSTATE_SINGLE *state)
4567{
4568	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
4569	struct si_power_info *si_pi = si_get_pi(rdev);
4570	struct si_ulv_param *ulv = &si_pi->ulv;
4571	u32 sclk_in_sr = 1350; /* ??? */
4572	int ret;
4573
4574	ret = si_convert_power_level_to_smc(rdev, &ulv->pl,
4575					    &state->level);
4576	if (!ret) {
4577		if (eg_pi->sclk_deep_sleep) {
4578			if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ)
4579				state->level.stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS;
4580			else
4581				state->level.stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE;
4582		}
4583		if (ulv->one_pcie_lane_in_ulv)
4584			state->flags |= PPSMC_SWSTATE_FLAG_PCIE_X1;
4585		state->level.arbRefreshState = (u8)(SISLANDS_ULV_STATE_ARB_INDEX);
4586		state->level.ACIndex = 1;
4587		state->level.std_vddc = state->level.vddc;
4588		state->levelCount = 1;
4589
4590		state->flags |= PPSMC_SWSTATE_FLAG_DC;
4591	}
4592
4593	return ret;
4594}
4595
4596static int si_program_ulv_memory_timing_parameters(struct radeon_device *rdev)
4597{
4598	struct si_power_info *si_pi = si_get_pi(rdev);
4599	struct si_ulv_param *ulv = &si_pi->ulv;
4600	SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };
4601	int ret;
4602
4603	ret = si_populate_memory_timing_parameters(rdev, &ulv->pl,
4604						   &arb_regs);
4605	if (ret)
4606		return ret;
4607
4608	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_ulv_volt_change_delay,
4609				   ulv->volt_change_delay);
4610
4611	ret = si_copy_bytes_to_smc(rdev,
4612				   si_pi->arb_table_start +
4613				   offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) +
4614				   sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX,
4615				   (u8 *)&arb_regs,
4616				   sizeof(SMC_SIslands_MCArbDramTimingRegisterSet),
4617				   si_pi->sram_end);
4618
4619	return ret;
4620}
4621
4622static void si_get_mvdd_configuration(struct radeon_device *rdev)
4623{
4624	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4625
4626	pi->mvdd_split_frequency = 30000;
4627}
4628
4629static int si_init_smc_table(struct radeon_device *rdev)
4630{
4631	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4632	struct si_power_info *si_pi = si_get_pi(rdev);
4633	struct radeon_ps *radeon_boot_state = rdev->pm.dpm.boot_ps;
4634	const struct si_ulv_param *ulv = &si_pi->ulv;
4635	SISLANDS_SMC_STATETABLE  *table = &si_pi->smc_statetable;
4636	int ret;
4637	u32 lane_width;
4638	u32 vr_hot_gpio;
4639
4640	si_populate_smc_voltage_tables(rdev, table);
4641
4642	switch (rdev->pm.int_thermal_type) {
4643	case THERMAL_TYPE_SI:
4644	case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
4645		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
4646		break;
4647	case THERMAL_TYPE_NONE:
4648		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;
4649		break;
4650	default:
4651		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
4652		break;
4653	}
4654
4655	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)
4656		table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
4657
4658	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT) {
4659		if ((rdev->pdev->device != 0x6818) && (rdev->pdev->device != 0x6819))
4660			table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT;
4661	}
4662
4663	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
4664		table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
4665
4666	if (pi->mem_gddr5)
4667		table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
4668
4669	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY)
4670		table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH;
4671
4672	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE) {
4673		table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO;
4674		vr_hot_gpio = rdev->pm.dpm.backbias_response_time;
4675		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_vr_hot_gpio,
4676					   vr_hot_gpio);
4677	}
4678
4679	ret = si_populate_smc_initial_state(rdev, radeon_boot_state, table);
4680	if (ret)
4681		return ret;
4682
4683	ret = si_populate_smc_acpi_state(rdev, table);
4684	if (ret)
4685		return ret;
4686
4687	table->driverState.flags = table->initialState.flags;
4688	table->driverState.levelCount = table->initialState.levelCount;
4689	table->driverState.levels[0] = table->initialState.level;
4690
4691	ret = si_do_program_memory_timing_parameters(rdev, radeon_boot_state,
4692						     SISLANDS_INITIAL_STATE_ARB_INDEX);
4693	if (ret)
4694		return ret;
4695
4696	if (ulv->supported && ulv->pl.vddc) {
4697		ret = si_populate_ulv_state(rdev, &table->ULVState);
4698		if (ret)
4699			return ret;
4700
4701		ret = si_program_ulv_memory_timing_parameters(rdev);
4702		if (ret)
4703			return ret;
4704
4705		WREG32(CG_ULV_CONTROL, ulv->cg_ulv_control);
4706		WREG32(CG_ULV_PARAMETER, ulv->cg_ulv_parameter);
4707
4708		lane_width = radeon_get_pcie_lanes(rdev);
4709		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width);
4710	} else {
4711		table->ULVState = table->initialState;
4712	}
4713
4714	return si_copy_bytes_to_smc(rdev, si_pi->state_table_start,
4715				    (u8 *)table, sizeof(SISLANDS_SMC_STATETABLE),
4716				    si_pi->sram_end);
4717}
4718
4719static int si_calculate_sclk_params(struct radeon_device *rdev,
4720				    u32 engine_clock,
4721				    SISLANDS_SMC_SCLK_VALUE *sclk)
4722{
4723	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4724	struct si_power_info *si_pi = si_get_pi(rdev);
4725	struct atom_clock_dividers dividers;
4726	u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl;
4727	u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2;
4728	u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3;
4729	u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4;
4730	u32 cg_spll_spread_spectrum = si_pi->clock_registers.cg_spll_spread_spectrum;
4731	u32 cg_spll_spread_spectrum_2 = si_pi->clock_registers.cg_spll_spread_spectrum_2;
4732	u64 tmp;
4733	u32 reference_clock = rdev->clock.spll.reference_freq;
4734	u32 reference_divider;
4735	u32 fbdiv;
4736	int ret;
4737
4738	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
4739					     engine_clock, false, &dividers);
4740	if (ret)
4741		return ret;
4742
4743	reference_divider = 1 + dividers.ref_div;
4744
4745	tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384;
4746	do_div(tmp, reference_clock);
4747	fbdiv = (u32) tmp;
4748
4749	spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK);
4750	spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
4751	spll_func_cntl |= SPLL_PDIV_A(dividers.post_div);
4752
4753	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
4754	spll_func_cntl_2 |= SCLK_MUX_SEL(2);
4755
4756	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
4757	spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
4758	spll_func_cntl_3 |= SPLL_DITHEN;
4759
4760	if (pi->sclk_ss) {
4761		struct radeon_atom_ss ss;
4762		u32 vco_freq = engine_clock * dividers.post_div;
4763
4764		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
4765						     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
4766			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
4767			u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
4768
4769			cg_spll_spread_spectrum &= ~CLK_S_MASK;
4770			cg_spll_spread_spectrum |= CLK_S(clk_s);
4771			cg_spll_spread_spectrum |= SSEN;
4772
4773			cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
4774			cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
4775		}
4776	}
4777
4778	sclk->sclk_value = engine_clock;
4779	sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl;
4780	sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2;
4781	sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3;
4782	sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4;
4783	sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum;
4784	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2;
4785
4786	return 0;
4787}
4788
4789static int si_populate_sclk_value(struct radeon_device *rdev,
4790				  u32 engine_clock,
4791				  SISLANDS_SMC_SCLK_VALUE *sclk)
4792{
4793	SISLANDS_SMC_SCLK_VALUE sclk_tmp;
4794	int ret;
4795
4796	ret = si_calculate_sclk_params(rdev, engine_clock, &sclk_tmp);
4797	if (!ret) {
4798		sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value);
4799		sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL);
4800		sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2);
4801		sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3);
4802		sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4);
4803		sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM);
4804		sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2);
4805	}
4806
4807	return ret;
4808}
4809
4810static int si_populate_mclk_value(struct radeon_device *rdev,
4811				  u32 engine_clock,
4812				  u32 memory_clock,
4813				  SISLANDS_SMC_MCLK_VALUE *mclk,
4814				  bool strobe_mode,
4815				  bool dll_state_on)
4816{
4817	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4818	struct si_power_info *si_pi = si_get_pi(rdev);
4819	u32  dll_cntl = si_pi->clock_registers.dll_cntl;
4820	u32  mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl;
4821	u32  mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl;
4822	u32  mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl;
4823	u32  mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl;
4824	u32  mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1;
4825	u32  mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2;
4826	u32  mpll_ss1 = si_pi->clock_registers.mpll_ss1;
4827	u32  mpll_ss2 = si_pi->clock_registers.mpll_ss2;
4828	struct atom_mpll_param mpll_param;
4829	int ret;
4830
4831	ret = radeon_atom_get_memory_pll_dividers(rdev, memory_clock, strobe_mode, &mpll_param);
4832	if (ret)
4833		return ret;
4834
4835	mpll_func_cntl &= ~BWCTRL_MASK;
4836	mpll_func_cntl |= BWCTRL(mpll_param.bwcntl);
4837
4838	mpll_func_cntl_1 &= ~(CLKF_MASK | CLKFRAC_MASK | VCO_MODE_MASK);
4839	mpll_func_cntl_1 |= CLKF(mpll_param.clkf) |
4840		CLKFRAC(mpll_param.clkfrac) | VCO_MODE(mpll_param.vco_mode);
4841
4842	mpll_ad_func_cntl &= ~YCLK_POST_DIV_MASK;
4843	mpll_ad_func_cntl |= YCLK_POST_DIV(mpll_param.post_div);
4844
4845	if (pi->mem_gddr5) {
4846		mpll_dq_func_cntl &= ~(YCLK_SEL_MASK | YCLK_POST_DIV_MASK);
4847		mpll_dq_func_cntl |= YCLK_SEL(mpll_param.yclk_sel) |
4848			YCLK_POST_DIV(mpll_param.post_div);
4849	}
4850
4851	if (pi->mclk_ss) {
4852		struct radeon_atom_ss ss;
4853		u32 freq_nom;
4854		u32 tmp;
4855		u32 reference_clock = rdev->clock.mpll.reference_freq;
4856
4857		if (pi->mem_gddr5)
4858			freq_nom = memory_clock * 4;
4859		else
4860			freq_nom = memory_clock * 2;
4861
4862		tmp = freq_nom / reference_clock;
4863		tmp = tmp * tmp;
4864		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
4865						     ASIC_INTERNAL_MEMORY_SS, freq_nom)) {
4866			u32 clks = reference_clock * 5 / ss.rate;
4867			u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom);
4868
4869			mpll_ss1 &= ~CLKV_MASK;
4870			mpll_ss1 |= CLKV(clkv);
4871
4872			mpll_ss2 &= ~CLKS_MASK;
4873			mpll_ss2 |= CLKS(clks);
4874		}
4875	}
4876
4877	mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
4878	mclk_pwrmgt_cntl |= DLL_SPEED(mpll_param.dll_speed);
4879
4880	if (dll_state_on)
4881		mclk_pwrmgt_cntl |= MRDCK0_PDNB | MRDCK1_PDNB;
4882	else
4883		mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB);
4884
4885	mclk->mclk_value = cpu_to_be32(memory_clock);
4886	mclk->vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl);
4887	mclk->vMPLL_FUNC_CNTL_1 = cpu_to_be32(mpll_func_cntl_1);
4888	mclk->vMPLL_FUNC_CNTL_2 = cpu_to_be32(mpll_func_cntl_2);
4889	mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
4890	mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
4891	mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
4892	mclk->vDLL_CNTL = cpu_to_be32(dll_cntl);
4893	mclk->vMPLL_SS = cpu_to_be32(mpll_ss1);
4894	mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2);
4895
4896	return 0;
4897}
4898
4899static void si_populate_smc_sp(struct radeon_device *rdev,
4900			       struct radeon_ps *radeon_state,
4901			       SISLANDS_SMC_SWSTATE *smc_state)
4902{
4903	struct ni_ps *ps = ni_get_ps(radeon_state);
4904	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4905	int i;
4906
4907	for (i = 0; i < ps->performance_level_count - 1; i++)
4908		smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);
4909
4910	smc_state->levels[ps->performance_level_count - 1].bSP =
4911		cpu_to_be32(pi->psp);
4912}
4913
4914static int si_convert_power_level_to_smc(struct radeon_device *rdev,
4915					 struct rv7xx_pl *pl,
4916					 SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level)
4917{
4918	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
4919	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
4920	struct si_power_info *si_pi = si_get_pi(rdev);
4921	int ret;
4922	bool dll_state_on;
4923	u16 std_vddc;
4924	bool gmc_pg = false;
4925
4926	if (eg_pi->pcie_performance_request &&
4927	    (si_pi->force_pcie_gen != RADEON_PCIE_GEN_INVALID))
4928		level->gen2PCIE = (u8)si_pi->force_pcie_gen;
4929	else
4930		level->gen2PCIE = (u8)pl->pcie_gen;
4931
4932	ret = si_populate_sclk_value(rdev, pl->sclk, &level->sclk);
4933	if (ret)
4934		return ret;
4935
4936	level->mcFlags =  0;
4937
4938	if (pi->mclk_stutter_mode_threshold &&
4939	    (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
4940	    !eg_pi->uvd_enabled &&
4941	    (RREG32(DPG_PIPE_STUTTER_CONTROL) & STUTTER_ENABLE) &&
4942	    (rdev->pm.dpm.new_active_crtc_count <= 2)) {
4943		level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN;
4944
4945		if (gmc_pg)
4946			level->mcFlags |= SISLANDS_SMC_MC_PG_EN;
4947	}
4948
4949	if (pi->mem_gddr5) {
4950		if (pl->mclk > pi->mclk_edc_enable_threshold)
4951			level->mcFlags |= SISLANDS_SMC_MC_EDC_RD_FLAG;
4952
4953		if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold)
4954			level->mcFlags |= SISLANDS_SMC_MC_EDC_WR_FLAG;
4955
4956		level->strobeMode = si_get_strobe_mode_settings(rdev, pl->mclk);
4957
4958		if (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) {
4959			if (si_get_mclk_frequency_ratio(pl->mclk, true) >=
4960			    ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf))
4961				dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
4962			else
4963				dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false;
4964		} else {
4965			dll_state_on = false;
4966		}
4967	} else {
4968		level->strobeMode = si_get_strobe_mode_settings(rdev,
4969								pl->mclk);
4970
4971		dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
4972	}
4973
4974	ret = si_populate_mclk_value(rdev,
4975				     pl->sclk,
4976				     pl->mclk,
4977				     &level->mclk,
4978				     (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) != 0, dll_state_on);
4979	if (ret)
4980		return ret;
4981
4982	ret = si_populate_voltage_value(rdev,
4983					&eg_pi->vddc_voltage_table,
4984					pl->vddc, &level->vddc);
4985	if (ret)
4986		return ret;
4987
4988
4989	ret = si_get_std_voltage_value(rdev, &level->vddc, &std_vddc);
4990	if (ret)
4991		return ret;
4992
4993	ret = si_populate_std_voltage_value(rdev, std_vddc,
4994					    level->vddc.index, &level->std_vddc);
4995	if (ret)
4996		return ret;
4997
4998	if (eg_pi->vddci_control) {
4999		ret = si_populate_voltage_value(rdev, &eg_pi->vddci_voltage_table,
5000						pl->vddci, &level->vddci);
5001		if (ret)
5002			return ret;
5003	}
5004
5005	if (si_pi->vddc_phase_shed_control) {
5006		ret = si_populate_phase_shedding_value(rdev,
5007						       &rdev->pm.dpm.dyn_state.phase_shedding_limits_table,
5008						       pl->vddc,
5009						       pl->sclk,
5010						       pl->mclk,
5011						       &level->vddc);
5012		if (ret)
5013			return ret;
5014	}
5015
5016	level->MaxPoweredUpCU = si_pi->max_cu;
5017
5018	ret = si_populate_mvdd_value(rdev, pl->mclk, &level->mvdd);
5019
5020	return ret;
5021}
5022
5023static int si_populate_smc_t(struct radeon_device *rdev,
5024			     struct radeon_ps *radeon_state,
5025			     SISLANDS_SMC_SWSTATE *smc_state)
5026{
5027	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
5028	struct ni_ps *state = ni_get_ps(radeon_state);
5029	u32 a_t;
5030	u32 t_l, t_h;
5031	u32 high_bsp;
5032	int i, ret;
5033
5034	if (state->performance_level_count >= 9)
5035		return -EINVAL;
5036
5037	if (state->performance_level_count < 2) {
5038		a_t = CG_R(0xffff) | CG_L(0);
5039		smc_state->levels[0].aT = cpu_to_be32(a_t);
5040		return 0;
5041	}
5042
5043	smc_state->levels[0].aT = cpu_to_be32(0);
5044
5045	for (i = 0; i <= state->performance_level_count - 2; i++) {
5046		ret = r600_calculate_at(
5047			(50 / SISLANDS_MAX_HARDWARE_POWERLEVELS) * 100 * (i + 1),
5048			100 * R600_AH_DFLT,
5049			state->performance_levels[i + 1].sclk,
5050			state->performance_levels[i].sclk,
5051			&t_l,
5052			&t_h);
5053
5054		if (ret) {
5055			t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT;
5056			t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT;
5057		}
5058
5059		a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK;
5060		a_t |= CG_R(t_l * pi->bsp / 20000);
5061		smc_state->levels[i].aT = cpu_to_be32(a_t);
5062
5063		high_bsp = (i == state->performance_level_count - 2) ?
5064			pi->pbsp : pi->bsp;
5065		a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000);
5066		smc_state->levels[i + 1].aT = cpu_to_be32(a_t);
5067	}
5068
5069	return 0;
5070}
5071
5072static int si_disable_ulv(struct radeon_device *rdev)
5073{
5074	struct si_power_info *si_pi = si_get_pi(rdev);
5075	struct si_ulv_param *ulv = &si_pi->ulv;
5076
5077	if (ulv->supported)
5078		return (si_send_msg_to_smc(rdev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ?
5079			0 : -EINVAL;
5080
5081	return 0;
5082}
5083
5084static bool si_is_state_ulv_compatible(struct radeon_device *rdev,
5085				       struct radeon_ps *radeon_state)
5086{
5087	const struct si_power_info *si_pi = si_get_pi(rdev);
5088	const struct si_ulv_param *ulv = &si_pi->ulv;
5089	const struct ni_ps *state = ni_get_ps(radeon_state);
5090	int i;
5091
5092	if (state->performance_levels[0].mclk != ulv->pl.mclk)
5093		return false;
5094
5095	/* XXX validate against display requirements! */
5096
5097	for (i = 0; i < rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) {
5098		if (rdev->clock.current_dispclk <=
5099		    rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) {
5100			if (ulv->pl.vddc <
5101			    rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v)
5102				return false;
5103		}
5104	}
5105
5106	if ((radeon_state->vclk != 0) || (radeon_state->dclk != 0))
5107		return false;
5108
5109	return true;
5110}
5111
5112static int si_set_power_state_conditionally_enable_ulv(struct radeon_device *rdev,
5113						       struct radeon_ps *radeon_new_state)
5114{
5115	const struct si_power_info *si_pi = si_get_pi(rdev);
5116	const struct si_ulv_param *ulv = &si_pi->ulv;
5117
5118	if (ulv->supported) {
5119		if (si_is_state_ulv_compatible(rdev, radeon_new_state))
5120			return (si_send_msg_to_smc(rdev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ?
5121				0 : -EINVAL;
5122	}
5123	return 0;
5124}
5125
5126static int si_convert_power_state_to_smc(struct radeon_device *rdev,
5127					 struct radeon_ps *radeon_state,
5128					 SISLANDS_SMC_SWSTATE *smc_state)
5129{
5130	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
5131	struct ni_power_info *ni_pi = ni_get_pi(rdev);
5132	struct si_power_info *si_pi = si_get_pi(rdev);
5133	struct ni_ps *state = ni_get_ps(radeon_state);
5134	int i, ret;
5135	u32 threshold;
5136	u32 sclk_in_sr = 1350; /* ??? */
5137
5138	if (state->performance_level_count > SISLANDS_MAX_HARDWARE_POWERLEVELS)
5139		return -EINVAL;
5140
5141	threshold = state->performance_levels[state->performance_level_count-1].sclk * 100 / 100;
5142
5143	if (radeon_state->vclk && radeon_state->dclk) {
5144		eg_pi->uvd_enabled = true;
5145		if (eg_pi->smu_uvd_hs)
5146			smc_state->flags |= PPSMC_SWSTATE_FLAG_UVD;
5147	} else {
5148		eg_pi->uvd_enabled = false;
5149	}
5150
5151	if (state->dc_compatible)
5152		smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
5153
5154	smc_state->levelCount = 0;
5155	for (i = 0; i < state->performance_level_count; i++) {
5156		if (eg_pi->sclk_deep_sleep) {
5157			if ((i == 0) || si_pi->sclk_deep_sleep_above_low) {
5158				if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ)
5159					smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS;
5160				else
5161					smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE;
5162			}
5163		}
5164
5165		ret = si_convert_power_level_to_smc(rdev, &state->performance_levels[i],
5166						    &smc_state->levels[i]);
5167		smc_state->levels[i].arbRefreshState =
5168			(u8)(SISLANDS_DRIVER_STATE_ARB_INDEX + i);
5169
5170		if (ret)
5171			return ret;
5172
5173		if (ni_pi->enable_power_containment)
5174			smc_state->levels[i].displayWatermark =
5175				(state->performance_levels[i].sclk < threshold) ?
5176				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
5177		else
5178			smc_state->levels[i].displayWatermark = (i < 2) ?
5179				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
5180
5181		if (eg_pi->dynamic_ac_timing)
5182			smc_state->levels[i].ACIndex = SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i;
5183		else
5184			smc_state->levels[i].ACIndex = 0;
5185
5186		smc_state->levelCount++;
5187	}
5188
5189	si_write_smc_soft_register(rdev,
5190				   SI_SMC_SOFT_REGISTER_watermark_threshold,
5191				   threshold / 512);
5192
5193	si_populate_smc_sp(rdev, radeon_state, smc_state);
5194
5195	ret = si_populate_power_containment_values(rdev, radeon_state, smc_state);
5196	if (ret)
5197		ni_pi->enable_power_containment = false;
5198
5199	ret = si_populate_sq_ramping_values(rdev, radeon_state, smc_state);
5200	if (ret)
5201		ni_pi->enable_sq_ramping = false;
5202
5203	return si_populate_smc_t(rdev, radeon_state, smc_state);
5204}
5205
5206static int si_upload_sw_state(struct radeon_device *rdev,
5207			      struct radeon_ps *radeon_new_state)
5208{
5209	struct si_power_info *si_pi = si_get_pi(rdev);
5210	struct ni_ps *new_state = ni_get_ps(radeon_new_state);
5211	int ret;
5212	u32 address = si_pi->state_table_start +
5213		offsetof(SISLANDS_SMC_STATETABLE, driverState);
5214	SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.driverState;
5215	size_t state_size = struct_size(smc_state, levels,
5216					new_state->performance_level_count);
5217
5218	memset(smc_state, 0, state_size);
5219
5220	ret = si_convert_power_state_to_smc(rdev, radeon_new_state, smc_state);
5221	if (ret)
5222		return ret;
5223
5224	ret = si_copy_bytes_to_smc(rdev, address, (u8 *)smc_state,
5225				   state_size, si_pi->sram_end);
5226
5227	return ret;
5228}
5229
5230static int si_upload_ulv_state(struct radeon_device *rdev)
5231{
5232	struct si_power_info *si_pi = si_get_pi(rdev);
5233	struct si_ulv_param *ulv = &si_pi->ulv;
5234	int ret = 0;
5235
5236	if (ulv->supported && ulv->pl.vddc) {
5237		u32 address = si_pi->state_table_start +
5238			offsetof(SISLANDS_SMC_STATETABLE, ULVState);
5239		struct SISLANDS_SMC_SWSTATE_SINGLE *smc_state = &si_pi->smc_statetable.ULVState;
5240		u32 state_size = sizeof(struct SISLANDS_SMC_SWSTATE_SINGLE);
5241
5242		memset(smc_state, 0, state_size);
5243
5244		ret = si_populate_ulv_state(rdev, smc_state);
5245		if (!ret)
5246			ret = si_copy_bytes_to_smc(rdev, address, (u8 *)smc_state,
5247						   state_size, si_pi->sram_end);
5248	}
5249
5250	return ret;
5251}
5252
5253static int si_upload_smc_data(struct radeon_device *rdev)
5254{
5255	struct radeon_crtc *radeon_crtc = NULL;
5256	int i;
5257
5258	if (rdev->pm.dpm.new_active_crtc_count == 0)
5259		return 0;
5260
5261	for (i = 0; i < rdev->num_crtc; i++) {
5262		if (rdev->pm.dpm.new_active_crtcs & (1 << i)) {
5263			radeon_crtc = rdev->mode_info.crtcs[i];
5264			break;
5265		}
5266	}
5267
5268	if (radeon_crtc == NULL)
5269		return 0;
5270
5271	if (radeon_crtc->line_time <= 0)
5272		return 0;
5273
5274	if (si_write_smc_soft_register(rdev,
5275				       SI_SMC_SOFT_REGISTER_crtc_index,
5276				       radeon_crtc->crtc_id) != PPSMC_Result_OK)
5277		return 0;
5278
5279	if (si_write_smc_soft_register(rdev,
5280				       SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min,
5281				       radeon_crtc->wm_high / radeon_crtc->line_time) != PPSMC_Result_OK)
5282		return 0;
5283
5284	if (si_write_smc_soft_register(rdev,
5285				       SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max,
5286				       radeon_crtc->wm_low / radeon_crtc->line_time) != PPSMC_Result_OK)
5287		return 0;
5288
5289	return 0;
5290}
5291
5292static int si_set_mc_special_registers(struct radeon_device *rdev,
5293				       struct si_mc_reg_table *table)
5294{
5295	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
5296	u8 i, j, k;
5297	u32 temp_reg;
5298
5299	for (i = 0, j = table->last; i < table->last; i++) {
5300		if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
5301			return -EINVAL;
5302		switch (table->mc_reg_address[i].s1 << 2) {
5303		case MC_SEQ_MISC1:
5304			temp_reg = RREG32(MC_PMG_CMD_EMRS);
5305			table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS >> 2;
5306			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
5307			for (k = 0; k < table->num_entries; k++)
5308				table->mc_reg_table_entry[k].mc_data[j] =
5309					((temp_reg & 0xffff0000)) |
5310					((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
5311			j++;
5312			if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
5313				return -EINVAL;
5314
5315			temp_reg = RREG32(MC_PMG_CMD_MRS);
5316			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS >> 2;
5317			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP >> 2;
5318			for (k = 0; k < table->num_entries; k++) {
5319				table->mc_reg_table_entry[k].mc_data[j] =
5320					(temp_reg & 0xffff0000) |
5321					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
5322				if (!pi->mem_gddr5)
5323					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
5324			}
5325			j++;
5326			if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
5327				return -EINVAL;
5328
5329			if (!pi->mem_gddr5) {
5330				table->mc_reg_address[j].s1 = MC_PMG_AUTO_CMD >> 2;
5331				table->mc_reg_address[j].s0 = MC_PMG_AUTO_CMD >> 2;
5332				for (k = 0; k < table->num_entries; k++)
5333					table->mc_reg_table_entry[k].mc_data[j] =
5334						(table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16;
5335				j++;
5336				if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
5337					return -EINVAL;
5338			}
5339			break;
5340		case MC_SEQ_RESERVE_M:
5341			temp_reg = RREG32(MC_PMG_CMD_MRS1);
5342			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1 >> 2;
5343			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
5344			for(k = 0; k < table->num_entries; k++)
5345				table->mc_reg_table_entry[k].mc_data[j] =
5346					(temp_reg & 0xffff0000) |
5347					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
5348			j++;
5349			if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
5350				return -EINVAL;
5351			break;
5352		default:
5353			break;
5354		}
5355	}
5356
5357	table->last = j;
5358
5359	return 0;
5360}
5361
5362static bool si_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)
5363{
5364	bool result = true;
5365
5366	switch (in_reg) {
5367	case  MC_SEQ_RAS_TIMING >> 2:
5368		*out_reg = MC_SEQ_RAS_TIMING_LP >> 2;
5369		break;
5370	case MC_SEQ_CAS_TIMING >> 2:
5371		*out_reg = MC_SEQ_CAS_TIMING_LP >> 2;
5372		break;
5373	case MC_SEQ_MISC_TIMING >> 2:
5374		*out_reg = MC_SEQ_MISC_TIMING_LP >> 2;
5375		break;
5376	case MC_SEQ_MISC_TIMING2 >> 2:
5377		*out_reg = MC_SEQ_MISC_TIMING2_LP >> 2;
5378		break;
5379	case MC_SEQ_RD_CTL_D0 >> 2:
5380		*out_reg = MC_SEQ_RD_CTL_D0_LP >> 2;
5381		break;
5382	case MC_SEQ_RD_CTL_D1 >> 2:
5383		*out_reg = MC_SEQ_RD_CTL_D1_LP >> 2;
5384		break;
5385	case MC_SEQ_WR_CTL_D0 >> 2:
5386		*out_reg = MC_SEQ_WR_CTL_D0_LP >> 2;
5387		break;
5388	case MC_SEQ_WR_CTL_D1 >> 2:
5389		*out_reg = MC_SEQ_WR_CTL_D1_LP >> 2;
5390		break;
5391	case MC_PMG_CMD_EMRS >> 2:
5392		*out_reg = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
5393		break;
5394	case MC_PMG_CMD_MRS >> 2:
5395		*out_reg = MC_SEQ_PMG_CMD_MRS_LP >> 2;
5396		break;
5397	case MC_PMG_CMD_MRS1 >> 2:
5398		*out_reg = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
5399		break;
5400	case MC_SEQ_PMG_TIMING >> 2:
5401		*out_reg = MC_SEQ_PMG_TIMING_LP >> 2;
5402		break;
5403	case MC_PMG_CMD_MRS2 >> 2:
5404		*out_reg = MC_SEQ_PMG_CMD_MRS2_LP >> 2;
5405		break;
5406	case MC_SEQ_WR_CTL_2 >> 2:
5407		*out_reg = MC_SEQ_WR_CTL_2_LP >> 2;
5408		break;
5409	default:
5410		result = false;
5411		break;
5412	}
5413
5414	return result;
5415}
5416
5417static void si_set_valid_flag(struct si_mc_reg_table *table)
5418{
5419	u8 i, j;
5420
5421	for (i = 0; i < table->last; i++) {
5422		for (j = 1; j < table->num_entries; j++) {
5423			if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) {
5424				table->valid_flag |= 1 << i;
5425				break;
5426			}
5427		}
5428	}
5429}
5430
5431static void si_set_s0_mc_reg_index(struct si_mc_reg_table *table)
5432{
5433	u32 i;
5434	u16 address;
5435
5436	for (i = 0; i < table->last; i++)
5437		table->mc_reg_address[i].s0 = si_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ?
5438			address : table->mc_reg_address[i].s1;
5439
5440}
5441
5442static int si_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table,
5443				      struct si_mc_reg_table *si_table)
5444{
5445	u8 i, j;
5446
5447	if (table->last > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
5448		return -EINVAL;
5449	if (table->num_entries > MAX_AC_TIMING_ENTRIES)
5450		return -EINVAL;
5451
5452	for (i = 0; i < table->last; i++)
5453		si_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
5454	si_table->last = table->last;
5455
5456	for (i = 0; i < table->num_entries; i++) {
5457		si_table->mc_reg_table_entry[i].mclk_max =
5458			table->mc_reg_table_entry[i].mclk_max;
5459		for (j = 0; j < table->last; j++) {
5460			si_table->mc_reg_table_entry[i].mc_data[j] =
5461				table->mc_reg_table_entry[i].mc_data[j];
5462		}
5463	}
5464	si_table->num_entries = table->num_entries;
5465
5466	return 0;
5467}
5468
5469static int si_initialize_mc_reg_table(struct radeon_device *rdev)
5470{
5471	struct si_power_info *si_pi = si_get_pi(rdev);
5472	struct atom_mc_reg_table *table;
5473	struct si_mc_reg_table *si_table = &si_pi->mc_reg_table;
5474	u8 module_index = rv770_get_memory_module_index(rdev);
5475	int ret;
5476
5477	table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL);
5478	if (!table)
5479		return -ENOMEM;
5480
5481	WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING));
5482	WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING));
5483	WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING));
5484	WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2));
5485	WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS));
5486	WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS));
5487	WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1));
5488	WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0));
5489	WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1));
5490	WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0));
5491	WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1));
5492	WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING));
5493	WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2));
5494	WREG32(MC_SEQ_WR_CTL_2_LP, RREG32(MC_SEQ_WR_CTL_2));
5495
5496	ret = radeon_atom_init_mc_reg_table(rdev, module_index, table);
5497	if (ret)
5498		goto init_mc_done;
5499
5500	ret = si_copy_vbios_mc_reg_table(table, si_table);
5501	if (ret)
5502		goto init_mc_done;
5503
5504	si_set_s0_mc_reg_index(si_table);
5505
5506	ret = si_set_mc_special_registers(rdev, si_table);
5507	if (ret)
5508		goto init_mc_done;
5509
5510	si_set_valid_flag(si_table);
5511
5512init_mc_done:
5513	kfree(table);
5514
5515	return ret;
5516
5517}
5518
5519static void si_populate_mc_reg_addresses(struct radeon_device *rdev,
5520					 SMC_SIslands_MCRegisters *mc_reg_table)
5521{
5522	struct si_power_info *si_pi = si_get_pi(rdev);
5523	u32 i, j;
5524
5525	for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) {
5526		if (si_pi->mc_reg_table.valid_flag & (1 << j)) {
5527			if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE)
5528				break;
5529			mc_reg_table->address[i].s0 =
5530				cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0);
5531			mc_reg_table->address[i].s1 =
5532				cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s1);
5533			i++;
5534		}
5535	}
5536	mc_reg_table->last = (u8)i;
5537}
5538
5539static void si_convert_mc_registers(const struct si_mc_reg_entry *entry,
5540				    SMC_SIslands_MCRegisterSet *data,
5541				    u32 num_entries, u32 valid_flag)
5542{
5543	u32 i, j;
5544
5545	for(i = 0, j = 0; j < num_entries; j++) {
5546		if (valid_flag & (1 << j)) {
5547			data->value[i] = cpu_to_be32(entry->mc_data[j]);
5548			i++;
5549		}
5550	}
5551}
5552
5553static void si_convert_mc_reg_table_entry_to_smc(struct radeon_device *rdev,
5554						 struct rv7xx_pl *pl,
5555						 SMC_SIslands_MCRegisterSet *mc_reg_table_data)
5556{
5557	struct si_power_info *si_pi = si_get_pi(rdev);
5558	u32 i = 0;
5559
5560	for (i = 0; i < si_pi->mc_reg_table.num_entries; i++) {
5561		if (pl->mclk <= si_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max)
5562			break;
5563	}
5564
5565	if ((i == si_pi->mc_reg_table.num_entries) && (i > 0))
5566		--i;
5567
5568	si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[i],
5569				mc_reg_table_data, si_pi->mc_reg_table.last,
5570				si_pi->mc_reg_table.valid_flag);
5571}
5572
5573static void si_convert_mc_reg_table_to_smc(struct radeon_device *rdev,
5574					   struct radeon_ps *radeon_state,
5575					   SMC_SIslands_MCRegisters *mc_reg_table)
5576{
5577	struct ni_ps *state = ni_get_ps(radeon_state);
5578	int i;
5579
5580	for (i = 0; i < state->performance_level_count; i++) {
5581		si_convert_mc_reg_table_entry_to_smc(rdev,
5582						     &state->performance_levels[i],
5583						     &mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]);
5584	}
5585}
5586
5587static int si_populate_mc_reg_table(struct radeon_device *rdev,
5588				    struct radeon_ps *radeon_boot_state)
5589{
5590	struct ni_ps *boot_state = ni_get_ps(radeon_boot_state);
5591	struct si_power_info *si_pi = si_get_pi(rdev);
5592	struct si_ulv_param *ulv = &si_pi->ulv;
5593	SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table;
5594
5595	memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters));
5596
5597	si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_seq_index, 1);
5598
5599	si_populate_mc_reg_addresses(rdev, smc_mc_reg_table);
5600
5601	si_convert_mc_reg_table_entry_to_smc(rdev, &boot_state->performance_levels[0],
5602					     &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_INITIAL_SLOT]);
5603
5604	si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0],
5605				&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ACPI_SLOT],
5606				si_pi->mc_reg_table.last,
5607				si_pi->mc_reg_table.valid_flag);
5608
5609	if (ulv->supported && ulv->pl.vddc != 0)
5610		si_convert_mc_reg_table_entry_to_smc(rdev, &ulv->pl,
5611						     &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT]);
5612	else
5613		si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0],
5614					&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT],
5615					si_pi->mc_reg_table.last,
5616					si_pi->mc_reg_table.valid_flag);
5617
5618	si_convert_mc_reg_table_to_smc(rdev, radeon_boot_state, smc_mc_reg_table);
5619
5620	return si_copy_bytes_to_smc(rdev, si_pi->mc_reg_table_start,
5621				    (u8 *)smc_mc_reg_table,
5622				    sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end);
5623}
5624
5625static int si_upload_mc_reg_table(struct radeon_device *rdev,
5626				  struct radeon_ps *radeon_new_state)
5627{
5628	struct ni_ps *new_state = ni_get_ps(radeon_new_state);
5629	struct si_power_info *si_pi = si_get_pi(rdev);
5630	u32 address = si_pi->mc_reg_table_start +
5631		offsetof(SMC_SIslands_MCRegisters,
5632			 data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]);
5633	SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table;
5634
5635	memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters));
5636
5637	si_convert_mc_reg_table_to_smc(rdev, radeon_new_state, smc_mc_reg_table);
5638
5639
5640	return si_copy_bytes_to_smc(rdev, address,
5641				    (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT],
5642				    sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count,
5643				    si_pi->sram_end);
5644
5645}
5646
5647static void si_enable_voltage_control(struct radeon_device *rdev, bool enable)
5648{
5649	if (enable)
5650		WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN);
5651	else
5652		WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN);
5653}
5654
5655static enum radeon_pcie_gen si_get_maximum_link_speed(struct radeon_device *rdev,
5656						      struct radeon_ps *radeon_state)
5657{
5658	struct ni_ps *state = ni_get_ps(radeon_state);
5659	int i;
5660	u16 pcie_speed, max_speed = 0;
5661
5662	for (i = 0; i < state->performance_level_count; i++) {
5663		pcie_speed = state->performance_levels[i].pcie_gen;
5664		if (max_speed < pcie_speed)
5665			max_speed = pcie_speed;
5666	}
5667	return max_speed;
5668}
5669
5670static u16 si_get_current_pcie_speed(struct radeon_device *rdev)
5671{
5672	u32 speed_cntl;
5673
5674	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL) & LC_CURRENT_DATA_RATE_MASK;
5675	speed_cntl >>= LC_CURRENT_DATA_RATE_SHIFT;
5676
5677	return (u16)speed_cntl;
5678}
5679
5680static void si_request_link_speed_change_before_state_change(struct radeon_device *rdev,
5681							     struct radeon_ps *radeon_new_state,
5682							     struct radeon_ps *radeon_current_state)
5683{
5684	struct si_power_info *si_pi = si_get_pi(rdev);
5685	enum radeon_pcie_gen target_link_speed = si_get_maximum_link_speed(rdev, radeon_new_state);
5686	enum radeon_pcie_gen current_link_speed;
5687
5688	if (si_pi->force_pcie_gen == RADEON_PCIE_GEN_INVALID)
5689		current_link_speed = si_get_maximum_link_speed(rdev, radeon_current_state);
5690	else
5691		current_link_speed = si_pi->force_pcie_gen;
5692
5693	si_pi->force_pcie_gen = RADEON_PCIE_GEN_INVALID;
5694	si_pi->pspp_notify_required = false;
5695	if (target_link_speed > current_link_speed) {
5696		switch (target_link_speed) {
5697#if defined(CONFIG_ACPI)
5698		case RADEON_PCIE_GEN3:
5699			if (radeon_acpi_pcie_performance_request(rdev, PCIE_PERF_REQ_PECI_GEN3, false) == 0)
5700				break;
5701			si_pi->force_pcie_gen = RADEON_PCIE_GEN2;
5702			if (current_link_speed == RADEON_PCIE_GEN2)
5703				break;
5704			fallthrough;
5705		case RADEON_PCIE_GEN2:
5706			if (radeon_acpi_pcie_performance_request(rdev, PCIE_PERF_REQ_PECI_GEN2, false) == 0)
5707				break;
5708			fallthrough;
5709#endif
5710		default:
5711			si_pi->force_pcie_gen = si_get_current_pcie_speed(rdev);
5712			break;
5713		}
5714	} else {
5715		if (target_link_speed < current_link_speed)
5716			si_pi->pspp_notify_required = true;
5717	}
5718}
5719
5720static void si_notify_link_speed_change_after_state_change(struct radeon_device *rdev,
5721							   struct radeon_ps *radeon_new_state,
5722							   struct radeon_ps *radeon_current_state)
5723{
5724	struct si_power_info *si_pi = si_get_pi(rdev);
5725	enum radeon_pcie_gen target_link_speed = si_get_maximum_link_speed(rdev, radeon_new_state);
5726	u8 request;
5727
5728	if (si_pi->pspp_notify_required) {
5729		if (target_link_speed == RADEON_PCIE_GEN3)
5730			request = PCIE_PERF_REQ_PECI_GEN3;
5731		else if (target_link_speed == RADEON_PCIE_GEN2)
5732			request = PCIE_PERF_REQ_PECI_GEN2;
5733		else
5734			request = PCIE_PERF_REQ_PECI_GEN1;
5735
5736		if ((request == PCIE_PERF_REQ_PECI_GEN1) &&
5737		    (si_get_current_pcie_speed(rdev) > 0))
5738			return;
5739
5740#if defined(CONFIG_ACPI)
5741		radeon_acpi_pcie_performance_request(rdev, request, false);
5742#endif
5743	}
5744}
5745
5746#if 0
5747static int si_ds_request(struct radeon_device *rdev,
5748			 bool ds_status_on, u32 count_write)
5749{
5750	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
5751
5752	if (eg_pi->sclk_deep_sleep) {
5753		if (ds_status_on)
5754			return (si_send_msg_to_smc(rdev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) ==
5755				PPSMC_Result_OK) ?
5756				0 : -EINVAL;
5757		else
5758			return (si_send_msg_to_smc(rdev, PPSMC_MSG_ThrottleOVRDSCLKDS) ==
5759				PPSMC_Result_OK) ? 0 : -EINVAL;
5760	}
5761	return 0;
5762}
5763#endif
5764
5765static void si_set_max_cu_value(struct radeon_device *rdev)
5766{
5767	struct si_power_info *si_pi = si_get_pi(rdev);
5768
5769	if (rdev->family == CHIP_VERDE) {
5770		switch (rdev->pdev->device) {
5771		case 0x6820:
5772		case 0x6825:
5773		case 0x6821:
5774		case 0x6823:
5775		case 0x6827:
5776			si_pi->max_cu = 10;
5777			break;
5778		case 0x682D:
5779		case 0x6824:
5780		case 0x682F:
5781		case 0x6826:
5782			si_pi->max_cu = 8;
5783			break;
5784		case 0x6828:
5785		case 0x6830:
5786		case 0x6831:
5787		case 0x6838:
5788		case 0x6839:
5789		case 0x683D:
5790			si_pi->max_cu = 10;
5791			break;
5792		case 0x683B:
5793		case 0x683F:
5794		case 0x6829:
5795			si_pi->max_cu = 8;
5796			break;
5797		default:
5798			si_pi->max_cu = 0;
5799			break;
5800		}
5801	} else {
5802		si_pi->max_cu = 0;
5803	}
5804}
5805
5806static int si_patch_single_dependency_table_based_on_leakage(struct radeon_device *rdev,
5807							     struct radeon_clock_voltage_dependency_table *table)
5808{
5809	u32 i;
5810	int j;
5811	u16 leakage_voltage;
5812
5813	if (table) {
5814		for (i = 0; i < table->count; i++) {
5815			switch (si_get_leakage_voltage_from_leakage_index(rdev,
5816									  table->entries[i].v,
5817									  &leakage_voltage)) {
5818			case 0:
5819				table->entries[i].v = leakage_voltage;
5820				break;
5821			case -EAGAIN:
5822				return -EINVAL;
5823			case -EINVAL:
5824			default:
5825				break;
5826			}
5827		}
5828
5829		for (j = (table->count - 2); j >= 0; j--) {
5830			table->entries[j].v = (table->entries[j].v <= table->entries[j + 1].v) ?
5831				table->entries[j].v : table->entries[j + 1].v;
5832		}
5833	}
5834	return 0;
5835}
5836
5837static int si_patch_dependency_tables_based_on_leakage(struct radeon_device *rdev)
5838{
5839	int ret;
5840
5841	ret = si_patch_single_dependency_table_based_on_leakage(rdev,
5842								&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk);
5843	ret = si_patch_single_dependency_table_based_on_leakage(rdev,
5844								&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk);
5845	ret = si_patch_single_dependency_table_based_on_leakage(rdev,
5846								&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk);
5847	return ret;
5848}
5849
5850static void si_set_pcie_lane_width_in_smc(struct radeon_device *rdev,
5851					  struct radeon_ps *radeon_new_state,
5852					  struct radeon_ps *radeon_current_state)
5853{
5854	u32 lane_width;
5855	u32 new_lane_width =
5856		((radeon_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
5857	u32 current_lane_width =
5858		((radeon_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;
5859
5860	if (new_lane_width != current_lane_width) {
5861		radeon_set_pcie_lanes(rdev, new_lane_width);
5862		lane_width = radeon_get_pcie_lanes(rdev);
5863		si_write_smc_soft_register(rdev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width);
5864	}
5865}
5866
5867static void si_set_vce_clock(struct radeon_device *rdev,
5868			     struct radeon_ps *new_rps,
5869			     struct radeon_ps *old_rps)
5870{
5871	if ((old_rps->evclk != new_rps->evclk) ||
5872	    (old_rps->ecclk != new_rps->ecclk)) {
5873		/* turn the clocks on when encoding, off otherwise */
5874		if (new_rps->evclk || new_rps->ecclk)
5875			vce_v1_0_enable_mgcg(rdev, false);
5876		else
5877			vce_v1_0_enable_mgcg(rdev, true);
5878		radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
5879	}
5880}
5881
5882void si_dpm_setup_asic(struct radeon_device *rdev)
5883{
5884	int r;
5885
5886	r = si_mc_load_microcode(rdev);
5887	if (r)
5888		DRM_ERROR("Failed to load MC firmware!\n");
5889	rv770_get_memory_type(rdev);
5890	si_read_clock_registers(rdev);
5891	si_enable_acpi_power_management(rdev);
5892}
5893
5894static int si_thermal_enable_alert(struct radeon_device *rdev,
5895				   bool enable)
5896{
5897	u32 thermal_int = RREG32(CG_THERMAL_INT);
5898
5899	if (enable) {
5900		PPSMC_Result result;
5901
5902		thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW);
5903		WREG32(CG_THERMAL_INT, thermal_int);
5904		rdev->irq.dpm_thermal = false;
5905		result = si_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
5906		if (result != PPSMC_Result_OK) {
5907			DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
5908			return -EINVAL;
5909		}
5910	} else {
5911		thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW;
5912		WREG32(CG_THERMAL_INT, thermal_int);
5913		rdev->irq.dpm_thermal = true;
5914	}
5915
5916	return 0;
5917}
5918
5919static int si_thermal_set_temperature_range(struct radeon_device *rdev,
5920					    int min_temp, int max_temp)
5921{
5922	int low_temp = 0 * 1000;
5923	int high_temp = 255 * 1000;
5924
5925	if (low_temp < min_temp)
5926		low_temp = min_temp;
5927	if (high_temp > max_temp)
5928		high_temp = max_temp;
5929	if (high_temp < low_temp) {
5930		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
5931		return -EINVAL;
5932	}
5933
5934	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK);
5935	WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK);
5936	WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK);
5937
5938	rdev->pm.dpm.thermal.min_temp = low_temp;
5939	rdev->pm.dpm.thermal.max_temp = high_temp;
5940
5941	return 0;
5942}
5943
5944static void si_fan_ctrl_set_static_mode(struct radeon_device *rdev, u32 mode)
5945{
5946	struct si_power_info *si_pi = si_get_pi(rdev);
5947	u32 tmp;
5948
5949	if (si_pi->fan_ctrl_is_in_default_mode) {
5950		tmp = (RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT;
5951		si_pi->fan_ctrl_default_mode = tmp;
5952		tmp = (RREG32(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT;
5953		si_pi->t_min = tmp;
5954		si_pi->fan_ctrl_is_in_default_mode = false;
5955	}
5956
5957	tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK;
5958	tmp |= TMIN(0);
5959	WREG32(CG_FDO_CTRL2, tmp);
5960
5961	tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK;
5962	tmp |= FDO_PWM_MODE(mode);
5963	WREG32(CG_FDO_CTRL2, tmp);
5964}
5965
5966static int si_thermal_setup_fan_table(struct radeon_device *rdev)
5967{
5968	struct si_power_info *si_pi = si_get_pi(rdev);
5969	PP_SIslands_FanTable fan_table = { FDO_MODE_HARDWARE };
5970	u32 duty100;
5971	u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2;
5972	u16 fdo_min, slope1, slope2;
5973	u32 reference_clock, tmp;
5974	int ret;
5975	u64 tmp64;
5976
5977	if (!si_pi->fan_table_start) {
5978		rdev->pm.dpm.fan.ucode_fan_control = false;
5979		return 0;
5980	}
5981
5982	duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
5983
5984	if (duty100 == 0) {
5985		rdev->pm.dpm.fan.ucode_fan_control = false;
5986		return 0;
5987	}
5988
5989	tmp64 = (u64)rdev->pm.dpm.fan.pwm_min * duty100;
5990	do_div(tmp64, 10000);
5991	fdo_min = (u16)tmp64;
5992
5993	t_diff1 = rdev->pm.dpm.fan.t_med - rdev->pm.dpm.fan.t_min;
5994	t_diff2 = rdev->pm.dpm.fan.t_high - rdev->pm.dpm.fan.t_med;
5995
5996	pwm_diff1 = rdev->pm.dpm.fan.pwm_med - rdev->pm.dpm.fan.pwm_min;
5997	pwm_diff2 = rdev->pm.dpm.fan.pwm_high - rdev->pm.dpm.fan.pwm_med;
5998
5999	slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
6000	slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
6001
6002	fan_table.temp_min = cpu_to_be16((50 + rdev->pm.dpm.fan.t_min) / 100);
6003	fan_table.temp_med = cpu_to_be16((50 + rdev->pm.dpm.fan.t_med) / 100);
6004	fan_table.temp_max = cpu_to_be16((50 + rdev->pm.dpm.fan.t_max) / 100);
6005
6006	fan_table.slope1 = cpu_to_be16(slope1);
6007	fan_table.slope2 = cpu_to_be16(slope2);
6008
6009	fan_table.fdo_min = cpu_to_be16(fdo_min);
6010
6011	fan_table.hys_down = cpu_to_be16(rdev->pm.dpm.fan.t_hyst);
6012
6013	fan_table.hys_up = cpu_to_be16(1);
6014
6015	fan_table.hys_slope = cpu_to_be16(1);
6016
6017	fan_table.temp_resp_lim = cpu_to_be16(5);
6018
6019	reference_clock = radeon_get_xclk(rdev);
6020
6021	fan_table.refresh_period = cpu_to_be32((rdev->pm.dpm.fan.cycle_delay *
6022						reference_clock) / 1600);
6023
6024	fan_table.fdo_max = cpu_to_be16((u16)duty100);
6025
6026	tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT;
6027	fan_table.temp_src = (uint8_t)tmp;
6028
6029	ret = si_copy_bytes_to_smc(rdev,
6030				   si_pi->fan_table_start,
6031				   (u8 *)(&fan_table),
6032				   sizeof(fan_table),
6033				   si_pi->sram_end);
6034
6035	if (ret) {
6036		DRM_ERROR("Failed to load fan table to the SMC.");
6037		rdev->pm.dpm.fan.ucode_fan_control = false;
6038	}
6039
6040	return 0;
6041}
6042
6043static int si_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev)
6044{
6045	struct si_power_info *si_pi = si_get_pi(rdev);
6046	PPSMC_Result ret;
6047
6048	ret = si_send_msg_to_smc(rdev, PPSMC_StartFanControl);
6049	if (ret == PPSMC_Result_OK) {
6050		si_pi->fan_is_controlled_by_smc = true;
6051		return 0;
6052	} else {
6053		return -EINVAL;
6054	}
6055}
6056
6057static int si_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev)
6058{
6059	struct si_power_info *si_pi = si_get_pi(rdev);
6060	PPSMC_Result ret;
6061
6062	ret = si_send_msg_to_smc(rdev, PPSMC_StopFanControl);
6063
6064	if (ret == PPSMC_Result_OK) {
6065		si_pi->fan_is_controlled_by_smc = false;
6066		return 0;
6067	} else {
6068		return -EINVAL;
6069	}
6070}
6071
6072int si_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev,
6073				      u32 *speed)
6074{
6075	u32 duty, duty100;
6076	u64 tmp64;
6077
6078	if (rdev->pm.no_fan)
6079		return -ENOENT;
6080
6081	duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
6082	duty = (RREG32(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT;
6083
6084	if (duty100 == 0)
6085		return -EINVAL;
6086
6087	tmp64 = (u64)duty * 100;
6088	do_div(tmp64, duty100);
6089	*speed = (u32)tmp64;
6090
6091	if (*speed > 100)
6092		*speed = 100;
6093
6094	return 0;
6095}
6096
6097int si_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,
6098				      u32 speed)
6099{
6100	struct si_power_info *si_pi = si_get_pi(rdev);
6101	u32 tmp;
6102	u32 duty, duty100;
6103	u64 tmp64;
6104
6105	if (rdev->pm.no_fan)
6106		return -ENOENT;
6107
6108	if (si_pi->fan_is_controlled_by_smc)
6109		return -EINVAL;
6110
6111	if (speed > 100)
6112		return -EINVAL;
6113
6114	duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT;
6115
6116	if (duty100 == 0)
6117		return -EINVAL;
6118
6119	tmp64 = (u64)speed * duty100;
6120	do_div(tmp64, 100);
6121	duty = (u32)tmp64;
6122
6123	tmp = RREG32(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK;
6124	tmp |= FDO_STATIC_DUTY(duty);
6125	WREG32(CG_FDO_CTRL0, tmp);
6126
6127	return 0;
6128}
6129
6130void si_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode)
6131{
6132	if (mode) {
6133		/* stop auto-manage */
6134		if (rdev->pm.dpm.fan.ucode_fan_control)
6135			si_fan_ctrl_stop_smc_fan_control(rdev);
6136		si_fan_ctrl_set_static_mode(rdev, mode);
6137	} else {
6138		/* restart auto-manage */
6139		if (rdev->pm.dpm.fan.ucode_fan_control)
6140			si_thermal_start_smc_fan_control(rdev);
6141		else
6142			si_fan_ctrl_set_default_mode(rdev);
6143	}
6144}
6145
6146u32 si_fan_ctrl_get_mode(struct radeon_device *rdev)
6147{
6148	struct si_power_info *si_pi = si_get_pi(rdev);
6149	u32 tmp;
6150
6151	if (si_pi->fan_is_controlled_by_smc)
6152		return 0;
6153
6154	tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK;
6155	return (tmp >> FDO_PWM_MODE_SHIFT);
6156}
6157
6158#if 0
6159static int si_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev,
6160					 u32 *speed)
6161{
6162	u32 tach_period;
6163	u32 xclk = radeon_get_xclk(rdev);
6164
6165	if (rdev->pm.no_fan)
6166		return -ENOENT;
6167
6168	if (rdev->pm.fan_pulses_per_revolution == 0)
6169		return -ENOENT;
6170
6171	tach_period = (RREG32(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT;
6172	if (tach_period == 0)
6173		return -ENOENT;
6174
6175	*speed = 60 * xclk * 10000 / tach_period;
6176
6177	return 0;
6178}
6179
6180static int si_fan_ctrl_set_fan_speed_rpm(struct radeon_device *rdev,
6181					 u32 speed)
6182{
6183	u32 tach_period, tmp;
6184	u32 xclk = radeon_get_xclk(rdev);
6185
6186	if (rdev->pm.no_fan)
6187		return -ENOENT;
6188
6189	if (rdev->pm.fan_pulses_per_revolution == 0)
6190		return -ENOENT;
6191
6192	if ((speed < rdev->pm.fan_min_rpm) ||
6193	    (speed > rdev->pm.fan_max_rpm))
6194		return -EINVAL;
6195
6196	if (rdev->pm.dpm.fan.ucode_fan_control)
6197		si_fan_ctrl_stop_smc_fan_control(rdev);
6198
6199	tach_period = 60 * xclk * 10000 / (8 * speed);
6200	tmp = RREG32(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK;
6201	tmp |= TARGET_PERIOD(tach_period);
6202	WREG32(CG_TACH_CTRL, tmp);
6203
6204	si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC_RPM);
6205
6206	return 0;
6207}
6208#endif
6209
6210static void si_fan_ctrl_set_default_mode(struct radeon_device *rdev)
6211{
6212	struct si_power_info *si_pi = si_get_pi(rdev);
6213	u32 tmp;
6214
6215	if (!si_pi->fan_ctrl_is_in_default_mode) {
6216		tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK;
6217		tmp |= FDO_PWM_MODE(si_pi->fan_ctrl_default_mode);
6218		WREG32(CG_FDO_CTRL2, tmp);
6219
6220		tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK;
6221		tmp |= TMIN(si_pi->t_min);
6222		WREG32(CG_FDO_CTRL2, tmp);
6223		si_pi->fan_ctrl_is_in_default_mode = true;
6224	}
6225}
6226
6227static void si_thermal_start_smc_fan_control(struct radeon_device *rdev)
6228{
6229	if (rdev->pm.dpm.fan.ucode_fan_control) {
6230		si_fan_ctrl_start_smc_fan_control(rdev);
6231		si_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC);
6232	}
6233}
6234
6235static void si_thermal_initialize(struct radeon_device *rdev)
6236{
6237	u32 tmp;
6238
6239	if (rdev->pm.fan_pulses_per_revolution) {
6240		tmp = RREG32(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK;
6241		tmp |= EDGE_PER_REV(rdev->pm.fan_pulses_per_revolution -1);
6242		WREG32(CG_TACH_CTRL, tmp);
6243	}
6244
6245	tmp = RREG32(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK;
6246	tmp |= TACH_PWM_RESP_RATE(0x28);
6247	WREG32(CG_FDO_CTRL2, tmp);
6248}
6249
6250static int si_thermal_start_thermal_controller(struct radeon_device *rdev)
6251{
6252	int ret;
6253
6254	si_thermal_initialize(rdev);
6255	ret = si_thermal_set_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
6256	if (ret)
6257		return ret;
6258	ret = si_thermal_enable_alert(rdev, true);
6259	if (ret)
6260		return ret;
6261	if (rdev->pm.dpm.fan.ucode_fan_control) {
6262		ret = si_halt_smc(rdev);
6263		if (ret)
6264			return ret;
6265		ret = si_thermal_setup_fan_table(rdev);
6266		if (ret)
6267			return ret;
6268		ret = si_resume_smc(rdev);
6269		if (ret)
6270			return ret;
6271		si_thermal_start_smc_fan_control(rdev);
6272	}
6273
6274	return 0;
6275}
6276
6277static void si_thermal_stop_thermal_controller(struct radeon_device *rdev)
6278{
6279	if (!rdev->pm.no_fan) {
6280		si_fan_ctrl_set_default_mode(rdev);
6281		si_fan_ctrl_stop_smc_fan_control(rdev);
6282	}
6283}
6284
6285int si_dpm_enable(struct radeon_device *rdev)
6286{
6287	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
6288	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
6289	struct si_power_info *si_pi = si_get_pi(rdev);
6290	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
6291	int ret;
6292
6293	if (si_is_smc_running(rdev))
6294		return -EINVAL;
6295	if (pi->voltage_control || si_pi->voltage_control_svi2)
6296		si_enable_voltage_control(rdev, true);
6297	if (pi->mvdd_control)
6298		si_get_mvdd_configuration(rdev);
6299	if (pi->voltage_control || si_pi->voltage_control_svi2) {
6300		ret = si_construct_voltage_tables(rdev);
6301		if (ret) {
6302			DRM_ERROR("si_construct_voltage_tables failed\n");
6303			return ret;
6304		}
6305	}
6306	if (eg_pi->dynamic_ac_timing) {
6307		ret = si_initialize_mc_reg_table(rdev);
6308		if (ret)
6309			eg_pi->dynamic_ac_timing = false;
6310	}
6311	if (pi->dynamic_ss)
6312		si_enable_spread_spectrum(rdev, true);
6313	if (pi->thermal_protection)
6314		si_enable_thermal_protection(rdev, true);
6315	si_setup_bsp(rdev);
6316	si_program_git(rdev);
6317	si_program_tp(rdev);
6318	si_program_tpp(rdev);
6319	si_program_sstp(rdev);
6320	si_enable_display_gap(rdev);
6321	si_program_vc(rdev);
6322	ret = si_upload_firmware(rdev);
6323	if (ret) {
6324		DRM_ERROR("si_upload_firmware failed\n");
6325		return ret;
6326	}
6327	ret = si_process_firmware_header(rdev);
6328	if (ret) {
6329		DRM_ERROR("si_process_firmware_header failed\n");
6330		return ret;
6331	}
6332	ret = si_initial_switch_from_arb_f0_to_f1(rdev);
6333	if (ret) {
6334		DRM_ERROR("si_initial_switch_from_arb_f0_to_f1 failed\n");
6335		return ret;
6336	}
6337	ret = si_init_smc_table(rdev);
6338	if (ret) {
6339		DRM_ERROR("si_init_smc_table failed\n");
6340		return ret;
6341	}
6342	ret = si_init_smc_spll_table(rdev);
6343	if (ret) {
6344		DRM_ERROR("si_init_smc_spll_table failed\n");
6345		return ret;
6346	}
6347	ret = si_init_arb_table_index(rdev);
6348	if (ret) {
6349		DRM_ERROR("si_init_arb_table_index failed\n");
6350		return ret;
6351	}
6352	if (eg_pi->dynamic_ac_timing) {
6353		ret = si_populate_mc_reg_table(rdev, boot_ps);
6354		if (ret) {
6355			DRM_ERROR("si_populate_mc_reg_table failed\n");
6356			return ret;
6357		}
6358	}
6359	ret = si_initialize_smc_cac_tables(rdev);
6360	if (ret) {
6361		DRM_ERROR("si_initialize_smc_cac_tables failed\n");
6362		return ret;
6363	}
6364	ret = si_initialize_hardware_cac_manager(rdev);
6365	if (ret) {
6366		DRM_ERROR("si_initialize_hardware_cac_manager failed\n");
6367		return ret;
6368	}
6369	ret = si_initialize_smc_dte_tables(rdev);
6370	if (ret) {
6371		DRM_ERROR("si_initialize_smc_dte_tables failed\n");
6372		return ret;
6373	}
6374	ret = si_populate_smc_tdp_limits(rdev, boot_ps);
6375	if (ret) {
6376		DRM_ERROR("si_populate_smc_tdp_limits failed\n");
6377		return ret;
6378	}
6379	ret = si_populate_smc_tdp_limits_2(rdev, boot_ps);
6380	if (ret) {
6381		DRM_ERROR("si_populate_smc_tdp_limits_2 failed\n");
6382		return ret;
6383	}
6384	si_program_response_times(rdev);
6385	si_program_ds_registers(rdev);
6386	si_dpm_start_smc(rdev);
6387	ret = si_notify_smc_display_change(rdev, false);
6388	if (ret) {
6389		DRM_ERROR("si_notify_smc_display_change failed\n");
6390		return ret;
6391	}
6392	si_enable_sclk_control(rdev, true);
6393	si_start_dpm(rdev);
6394
6395	si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
6396
6397	si_thermal_start_thermal_controller(rdev);
6398
6399	ni_update_current_ps(rdev, boot_ps);
6400
6401	return 0;
6402}
6403
6404static int si_set_temperature_range(struct radeon_device *rdev)
6405{
6406	int ret;
6407
6408	ret = si_thermal_enable_alert(rdev, false);
6409	if (ret)
6410		return ret;
6411	ret = si_thermal_set_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
6412	if (ret)
6413		return ret;
6414	ret = si_thermal_enable_alert(rdev, true);
6415	if (ret)
6416		return ret;
6417
6418	return ret;
6419}
6420
6421int si_dpm_late_enable(struct radeon_device *rdev)
6422{
6423	int ret;
6424
6425	ret = si_set_temperature_range(rdev);
6426	if (ret)
6427		return ret;
6428
6429	return ret;
6430}
6431
6432void si_dpm_disable(struct radeon_device *rdev)
6433{
6434	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
6435	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
6436
6437	if (!si_is_smc_running(rdev))
6438		return;
6439	si_thermal_stop_thermal_controller(rdev);
6440	si_disable_ulv(rdev);
6441	si_clear_vc(rdev);
6442	if (pi->thermal_protection)
6443		si_enable_thermal_protection(rdev, false);
6444	si_enable_power_containment(rdev, boot_ps, false);
6445	si_enable_smc_cac(rdev, boot_ps, false);
6446	si_enable_spread_spectrum(rdev, false);
6447	si_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, false);
6448	si_stop_dpm(rdev);
6449	si_reset_to_default(rdev);
6450	si_dpm_stop_smc(rdev);
6451	si_force_switch_to_arb_f0(rdev);
6452
6453	ni_update_current_ps(rdev, boot_ps);
6454}
6455
6456int si_dpm_pre_set_power_state(struct radeon_device *rdev)
6457{
6458	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
6459	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
6460	struct radeon_ps *new_ps = &requested_ps;
6461
6462	ni_update_requested_ps(rdev, new_ps);
6463
6464	si_apply_state_adjust_rules(rdev, &eg_pi->requested_rps);
6465
6466	return 0;
6467}
6468
6469static int si_power_control_set_level(struct radeon_device *rdev)
6470{
6471	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
6472	int ret;
6473
6474	ret = si_restrict_performance_levels_before_switch(rdev);
6475	if (ret)
6476		return ret;
6477	ret = si_halt_smc(rdev);
6478	if (ret)
6479		return ret;
6480	ret = si_populate_smc_tdp_limits(rdev, new_ps);
6481	if (ret)
6482		return ret;
6483	ret = si_populate_smc_tdp_limits_2(rdev, new_ps);
6484	if (ret)
6485		return ret;
6486	ret = si_resume_smc(rdev);
6487	if (ret)
6488		return ret;
6489	ret = si_set_sw_state(rdev);
6490	if (ret)
6491		return ret;
6492	return 0;
6493}
6494
6495int si_dpm_set_power_state(struct radeon_device *rdev)
6496{
6497	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
6498	struct radeon_ps *new_ps = &eg_pi->requested_rps;
6499	struct radeon_ps *old_ps = &eg_pi->current_rps;
6500	int ret;
6501
6502	ret = si_disable_ulv(rdev);
6503	if (ret) {
6504		DRM_ERROR("si_disable_ulv failed\n");
6505		return ret;
6506	}
6507	ret = si_restrict_performance_levels_before_switch(rdev);
6508	if (ret) {
6509		DRM_ERROR("si_restrict_performance_levels_before_switch failed\n");
6510		return ret;
6511	}
6512	if (eg_pi->pcie_performance_request)
6513		si_request_link_speed_change_before_state_change(rdev, new_ps, old_ps);
6514	ni_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
6515	ret = si_enable_power_containment(rdev, new_ps, false);
6516	if (ret) {
6517		DRM_ERROR("si_enable_power_containment failed\n");
6518		return ret;
6519	}
6520	ret = si_enable_smc_cac(rdev, new_ps, false);
6521	if (ret) {
6522		DRM_ERROR("si_enable_smc_cac failed\n");
6523		return ret;
6524	}
6525	ret = si_halt_smc(rdev);
6526	if (ret) {
6527		DRM_ERROR("si_halt_smc failed\n");
6528		return ret;
6529	}
6530	ret = si_upload_sw_state(rdev, new_ps);
6531	if (ret) {
6532		DRM_ERROR("si_upload_sw_state failed\n");
6533		return ret;
6534	}
6535	ret = si_upload_smc_data(rdev);
6536	if (ret) {
6537		DRM_ERROR("si_upload_smc_data failed\n");
6538		return ret;
6539	}
6540	ret = si_upload_ulv_state(rdev);
6541	if (ret) {
6542		DRM_ERROR("si_upload_ulv_state failed\n");
6543		return ret;
6544	}
6545	if (eg_pi->dynamic_ac_timing) {
6546		ret = si_upload_mc_reg_table(rdev, new_ps);
6547		if (ret) {
6548			DRM_ERROR("si_upload_mc_reg_table failed\n");
6549			return ret;
6550		}
6551	}
6552	ret = si_program_memory_timing_parameters(rdev, new_ps);
6553	if (ret) {
6554		DRM_ERROR("si_program_memory_timing_parameters failed\n");
6555		return ret;
6556	}
6557	si_set_pcie_lane_width_in_smc(rdev, new_ps, old_ps);
6558
6559	ret = si_resume_smc(rdev);
6560	if (ret) {
6561		DRM_ERROR("si_resume_smc failed\n");
6562		return ret;
6563	}
6564	ret = si_set_sw_state(rdev);
6565	if (ret) {
6566		DRM_ERROR("si_set_sw_state failed\n");
6567		return ret;
6568	}
6569	ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
6570	si_set_vce_clock(rdev, new_ps, old_ps);
6571	if (eg_pi->pcie_performance_request)
6572		si_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
6573	ret = si_set_power_state_conditionally_enable_ulv(rdev, new_ps);
6574	if (ret) {
6575		DRM_ERROR("si_set_power_state_conditionally_enable_ulv failed\n");
6576		return ret;
6577	}
6578	ret = si_enable_smc_cac(rdev, new_ps, true);
6579	if (ret) {
6580		DRM_ERROR("si_enable_smc_cac failed\n");
6581		return ret;
6582	}
6583	ret = si_enable_power_containment(rdev, new_ps, true);
6584	if (ret) {
6585		DRM_ERROR("si_enable_power_containment failed\n");
6586		return ret;
6587	}
6588
6589	ret = si_power_control_set_level(rdev);
6590	if (ret) {
6591		DRM_ERROR("si_power_control_set_level failed\n");
6592		return ret;
6593	}
6594
6595	return 0;
6596}
6597
6598void si_dpm_post_set_power_state(struct radeon_device *rdev)
6599{
6600	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
6601	struct radeon_ps *new_ps = &eg_pi->requested_rps;
6602
6603	ni_update_current_ps(rdev, new_ps);
6604}
6605
6606#if 0
6607void si_dpm_reset_asic(struct radeon_device *rdev)
6608{
6609	si_restrict_performance_levels_before_switch(rdev);
6610	si_disable_ulv(rdev);
6611	si_set_boot_state(rdev);
6612}
6613#endif
6614
6615void si_dpm_display_configuration_changed(struct radeon_device *rdev)
6616{
6617	si_program_display_gap(rdev);
6618}
6619
6620union power_info {
6621	struct _ATOM_POWERPLAY_INFO info;
6622	struct _ATOM_POWERPLAY_INFO_V2 info_2;
6623	struct _ATOM_POWERPLAY_INFO_V3 info_3;
6624	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
6625	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
6626	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
6627};
6628
6629union pplib_clock_info {
6630	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
6631	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
6632	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
6633	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
6634	struct _ATOM_PPLIB_SI_CLOCK_INFO si;
6635};
6636
6637union pplib_power_state {
6638	struct _ATOM_PPLIB_STATE v1;
6639	struct _ATOM_PPLIB_STATE_V2 v2;
6640};
6641
6642static void si_parse_pplib_non_clock_info(struct radeon_device *rdev,
6643					  struct radeon_ps *rps,
6644					  struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
6645					  u8 table_rev)
6646{
6647	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
6648	rps->class = le16_to_cpu(non_clock_info->usClassification);
6649	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
6650
6651	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
6652		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
6653		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
6654	} else if (r600_is_uvd_state(rps->class, rps->class2)) {
6655		rps->vclk = RV770_DEFAULT_VCLK_FREQ;
6656		rps->dclk = RV770_DEFAULT_DCLK_FREQ;
6657	} else {
6658		rps->vclk = 0;
6659		rps->dclk = 0;
6660	}
6661
6662	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
6663		rdev->pm.dpm.boot_ps = rps;
6664	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
6665		rdev->pm.dpm.uvd_ps = rps;
6666}
6667
6668static void si_parse_pplib_clock_info(struct radeon_device *rdev,
6669				      struct radeon_ps *rps, int index,
6670				      union pplib_clock_info *clock_info)
6671{
6672	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
6673	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
6674	struct si_power_info *si_pi = si_get_pi(rdev);
6675	struct ni_ps *ps = ni_get_ps(rps);
6676	u16 leakage_voltage;
6677	struct rv7xx_pl *pl = &ps->performance_levels[index];
6678	int ret;
6679
6680	ps->performance_level_count = index + 1;
6681
6682	pl->sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
6683	pl->sclk |= clock_info->si.ucEngineClockHigh << 16;
6684	pl->mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
6685	pl->mclk |= clock_info->si.ucMemoryClockHigh << 16;
6686
6687	pl->vddc = le16_to_cpu(clock_info->si.usVDDC);
6688	pl->vddci = le16_to_cpu(clock_info->si.usVDDCI);
6689	pl->flags = le32_to_cpu(clock_info->si.ulFlags);
6690	pl->pcie_gen = r600_get_pcie_gen_support(rdev,
6691						 si_pi->sys_pcie_mask,
6692						 si_pi->boot_pcie_gen,
6693						 clock_info->si.ucPCIEGen);
6694
6695	/* patch up vddc if necessary */
6696	ret = si_get_leakage_voltage_from_leakage_index(rdev, pl->vddc,
6697							&leakage_voltage);
6698	if (ret == 0)
6699		pl->vddc = leakage_voltage;
6700
6701	if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
6702		pi->acpi_vddc = pl->vddc;
6703		eg_pi->acpi_vddci = pl->vddci;
6704		si_pi->acpi_pcie_gen = pl->pcie_gen;
6705	}
6706
6707	if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) &&
6708	    index == 0) {
6709		/* XXX disable for A0 tahiti */
6710		si_pi->ulv.supported = false;
6711		si_pi->ulv.pl = *pl;
6712		si_pi->ulv.one_pcie_lane_in_ulv = false;
6713		si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT;
6714		si_pi->ulv.cg_ulv_parameter = SISLANDS_CGULVPARAMETER_DFLT;
6715		si_pi->ulv.cg_ulv_control = SISLANDS_CGULVCONTROL_DFLT;
6716	}
6717
6718	if (pi->min_vddc_in_table > pl->vddc)
6719		pi->min_vddc_in_table = pl->vddc;
6720
6721	if (pi->max_vddc_in_table < pl->vddc)
6722		pi->max_vddc_in_table = pl->vddc;
6723
6724	/* patch up boot state */
6725	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
6726		u16 vddc, vddci, mvdd;
6727		radeon_atombios_get_default_voltages(rdev, &vddc, &vddci, &mvdd);
6728		pl->mclk = rdev->clock.default_mclk;
6729		pl->sclk = rdev->clock.default_sclk;
6730		pl->vddc = vddc;
6731		pl->vddci = vddci;
6732		si_pi->mvdd_bootup_value = mvdd;
6733	}
6734
6735	if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
6736	    ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
6737		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
6738		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
6739		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
6740		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
6741	}
6742}
6743
6744static int si_parse_power_table(struct radeon_device *rdev)
6745{
6746	struct radeon_mode_info *mode_info = &rdev->mode_info;
6747	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
6748	union pplib_power_state *power_state;
6749	int i, j, k, non_clock_array_index, clock_array_index;
6750	union pplib_clock_info *clock_info;
6751	struct _StateArray *state_array;
6752	struct _ClockInfoArray *clock_info_array;
6753	struct _NonClockInfoArray *non_clock_info_array;
6754	union power_info *power_info;
6755	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
6756	u16 data_offset;
6757	u8 frev, crev;
6758	u8 *power_state_offset;
6759	struct ni_ps *ps;
6760
6761	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
6762				   &frev, &crev, &data_offset))
6763		return -EINVAL;
6764	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
6765
6766	state_array = (struct _StateArray *)
6767		(mode_info->atom_context->bios + data_offset +
6768		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
6769	clock_info_array = (struct _ClockInfoArray *)
6770		(mode_info->atom_context->bios + data_offset +
6771		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
6772	non_clock_info_array = (struct _NonClockInfoArray *)
6773		(mode_info->atom_context->bios + data_offset +
6774		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
6775
6776	rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
6777				  sizeof(struct radeon_ps),
6778				  GFP_KERNEL);
6779	if (!rdev->pm.dpm.ps)
6780		return -ENOMEM;
6781	power_state_offset = (u8 *)state_array->states;
6782	for (i = 0; i < state_array->ucNumEntries; i++) {
6783		u8 *idx;
6784		power_state = (union pplib_power_state *)power_state_offset;
6785		non_clock_array_index = power_state->v2.nonClockInfoIndex;
6786		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
6787			&non_clock_info_array->nonClockInfo[non_clock_array_index];
6788		if (!rdev->pm.power_state[i].clock_info)
6789			return -EINVAL;
6790		ps = kzalloc(sizeof(struct ni_ps), GFP_KERNEL);
6791		if (ps == NULL) {
6792			kfree(rdev->pm.dpm.ps);
6793			return -ENOMEM;
6794		}
6795		rdev->pm.dpm.ps[i].ps_priv = ps;
6796		si_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
6797					      non_clock_info,
6798					      non_clock_info_array->ucEntrySize);
6799		k = 0;
6800		idx = (u8 *)&power_state->v2.clockInfoIndex[0];
6801		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
6802			clock_array_index = idx[j];
6803			if (clock_array_index >= clock_info_array->ucNumEntries)
6804				continue;
6805			if (k >= SISLANDS_MAX_HARDWARE_POWERLEVELS)
6806				break;
6807			clock_info = (union pplib_clock_info *)
6808				((u8 *)&clock_info_array->clockInfo[0] +
6809				 (clock_array_index * clock_info_array->ucEntrySize));
6810			si_parse_pplib_clock_info(rdev,
6811						  &rdev->pm.dpm.ps[i], k,
6812						  clock_info);
6813			k++;
6814		}
6815		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
6816	}
6817	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
6818
6819	/* fill in the vce power states */
6820	for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
6821		u32 sclk, mclk;
6822		clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
6823		clock_info = (union pplib_clock_info *)
6824			&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
6825		sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
6826		sclk |= clock_info->si.ucEngineClockHigh << 16;
6827		mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
6828		mclk |= clock_info->si.ucMemoryClockHigh << 16;
6829		rdev->pm.dpm.vce_states[i].sclk = sclk;
6830		rdev->pm.dpm.vce_states[i].mclk = mclk;
6831	}
6832
6833	return 0;
6834}
6835
6836int si_dpm_init(struct radeon_device *rdev)
6837{
6838	struct rv7xx_power_info *pi;
6839	struct evergreen_power_info *eg_pi;
6840	struct ni_power_info *ni_pi;
6841	struct si_power_info *si_pi;
6842	struct atom_clock_dividers dividers;
6843	enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
6844	struct pci_dev *root = rdev->pdev->bus->self;
6845	int ret;
6846
6847	si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL);
6848	if (si_pi == NULL)
6849		return -ENOMEM;
6850	rdev->pm.dpm.priv = si_pi;
6851	ni_pi = &si_pi->ni;
6852	eg_pi = &ni_pi->eg;
6853	pi = &eg_pi->rv7xx;
6854
6855	if (!pci_is_root_bus(rdev->pdev->bus))
6856		speed_cap = pcie_get_speed_cap(root);
6857	if (speed_cap == PCI_SPEED_UNKNOWN) {
6858		si_pi->sys_pcie_mask = 0;
6859	} else {
6860		if (speed_cap == PCIE_SPEED_8_0GT)
6861			si_pi->sys_pcie_mask = RADEON_PCIE_SPEED_25 |
6862				RADEON_PCIE_SPEED_50 |
6863				RADEON_PCIE_SPEED_80;
6864		else if (speed_cap == PCIE_SPEED_5_0GT)
6865			si_pi->sys_pcie_mask = RADEON_PCIE_SPEED_25 |
6866				RADEON_PCIE_SPEED_50;
6867		else
6868			si_pi->sys_pcie_mask = RADEON_PCIE_SPEED_25;
6869	}
6870	si_pi->force_pcie_gen = RADEON_PCIE_GEN_INVALID;
6871	si_pi->boot_pcie_gen = si_get_current_pcie_speed(rdev);
6872
6873	si_set_max_cu_value(rdev);
6874
6875	rv770_get_max_vddc(rdev);
6876	si_get_leakage_vddc(rdev);
6877	si_patch_dependency_tables_based_on_leakage(rdev);
6878
6879	pi->acpi_vddc = 0;
6880	eg_pi->acpi_vddci = 0;
6881	pi->min_vddc_in_table = 0;
6882	pi->max_vddc_in_table = 0;
6883
6884	ret = r600_get_platform_caps(rdev);
6885	if (ret)
6886		return ret;
6887
6888	ret = r600_parse_extended_power_table(rdev);
6889	if (ret)
6890		return ret;
6891
6892	ret = si_parse_power_table(rdev);
6893	if (ret)
6894		return ret;
6895
6896	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
6897		kcalloc(4,
6898			sizeof(struct radeon_clock_voltage_dependency_entry),
6899			GFP_KERNEL);
6900	if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
6901		r600_free_extended_power_table(rdev);
6902		return -ENOMEM;
6903	}
6904	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
6905	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
6906	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
6907	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;
6908	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720;
6909	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;
6910	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810;
6911	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;
6912	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900;
6913
6914	if (rdev->pm.dpm.voltage_response_time == 0)
6915		rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
6916	if (rdev->pm.dpm.backbias_response_time == 0)
6917		rdev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;
6918
6919	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
6920					     0, false, &dividers);
6921	if (ret)
6922		pi->ref_div = dividers.ref_div + 1;
6923	else
6924		pi->ref_div = R600_REFERENCEDIVIDER_DFLT;
6925
6926	eg_pi->smu_uvd_hs = false;
6927
6928	pi->mclk_strobe_mode_threshold = 40000;
6929	if (si_is_special_1gb_platform(rdev))
6930		pi->mclk_stutter_mode_threshold = 0;
6931	else
6932		pi->mclk_stutter_mode_threshold = pi->mclk_strobe_mode_threshold;
6933	pi->mclk_edc_enable_threshold = 40000;
6934	eg_pi->mclk_edc_wr_enable_threshold = 40000;
6935
6936	ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;
6937
6938	pi->voltage_control =
6939		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6940					    VOLTAGE_OBJ_GPIO_LUT);
6941	if (!pi->voltage_control) {
6942		si_pi->voltage_control_svi2 =
6943			radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6944						    VOLTAGE_OBJ_SVID2);
6945		if (si_pi->voltage_control_svi2)
6946			radeon_atom_get_svi2_info(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6947						  &si_pi->svd_gpio_id, &si_pi->svc_gpio_id);
6948	}
6949
6950	pi->mvdd_control =
6951		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC,
6952					    VOLTAGE_OBJ_GPIO_LUT);
6953
6954	eg_pi->vddci_control =
6955		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
6956					    VOLTAGE_OBJ_GPIO_LUT);
6957	if (!eg_pi->vddci_control)
6958		si_pi->vddci_control_svi2 =
6959			radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI,
6960						    VOLTAGE_OBJ_SVID2);
6961
6962	si_pi->vddc_phase_shed_control =
6963		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC,
6964					    VOLTAGE_OBJ_PHASE_LUT);
6965
6966	rv770_get_engine_memory_ss(rdev);
6967
6968	pi->asi = RV770_ASI_DFLT;
6969	pi->pasi = CYPRESS_HASI_DFLT;
6970	pi->vrc = SISLANDS_VRC_DFLT;
6971
6972	pi->gfx_clock_gating = true;
6973
6974	eg_pi->sclk_deep_sleep = true;
6975	si_pi->sclk_deep_sleep_above_low = false;
6976
6977	if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
6978		pi->thermal_protection = true;
6979	else
6980		pi->thermal_protection = false;
6981
6982	eg_pi->dynamic_ac_timing = true;
6983
6984	eg_pi->light_sleep = true;
6985#if defined(CONFIG_ACPI)
6986	eg_pi->pcie_performance_request =
6987		radeon_acpi_is_pcie_performance_request_supported(rdev);
6988#else
6989	eg_pi->pcie_performance_request = false;
6990#endif
6991
6992	si_pi->sram_end = SMC_RAM_END;
6993
6994	rdev->pm.dpm.dyn_state.mclk_sclk_ratio = 4;
6995	rdev->pm.dpm.dyn_state.sclk_mclk_delta = 15000;
6996	rdev->pm.dpm.dyn_state.vddc_vddci_delta = 200;
6997	rdev->pm.dpm.dyn_state.valid_sclk_values.count = 0;
6998	rdev->pm.dpm.dyn_state.valid_sclk_values.values = NULL;
6999	rdev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
7000	rdev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
7001
7002	si_initialize_powertune_defaults(rdev);
7003
7004	/* make sure dc limits are valid */
7005	if ((rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) ||
7006	    (rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0))
7007		rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc =
7008			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
7009
7010	si_pi->fan_ctrl_is_in_default_mode = true;
7011
7012	return 0;
7013}
7014
7015void si_dpm_fini(struct radeon_device *rdev)
7016{
7017	int i;
7018
7019	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
7020		kfree(rdev->pm.dpm.ps[i].ps_priv);
7021	}
7022	kfree(rdev->pm.dpm.ps);
7023	kfree(rdev->pm.dpm.priv);
7024	kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);
7025	r600_free_extended_power_table(rdev);
7026}
7027
7028void si_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
7029						    struct seq_file *m)
7030{
7031	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
7032	struct radeon_ps *rps = &eg_pi->current_rps;
7033	struct ni_ps *ps = ni_get_ps(rps);
7034	struct rv7xx_pl *pl;
7035	u32 current_index =
7036		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
7037		CURRENT_STATE_INDEX_SHIFT;
7038
7039	if (current_index >= ps->performance_level_count) {
7040		seq_printf(m, "invalid dpm profile %d\n", current_index);
7041	} else {
7042		pl = &ps->performance_levels[current_index];
7043		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
7044		seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",
7045			   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
7046	}
7047}
7048
7049u32 si_dpm_get_current_sclk(struct radeon_device *rdev)
7050{
7051	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
7052	struct radeon_ps *rps = &eg_pi->current_rps;
7053	struct ni_ps *ps = ni_get_ps(rps);
7054	struct rv7xx_pl *pl;
7055	u32 current_index =
7056		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
7057		CURRENT_STATE_INDEX_SHIFT;
7058
7059	if (current_index >= ps->performance_level_count) {
7060		return 0;
7061	} else {
7062		pl = &ps->performance_levels[current_index];
7063		return pl->sclk;
7064	}
7065}
7066
7067u32 si_dpm_get_current_mclk(struct radeon_device *rdev)
7068{
7069	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
7070	struct radeon_ps *rps = &eg_pi->current_rps;
7071	struct ni_ps *ps = ni_get_ps(rps);
7072	struct rv7xx_pl *pl;
7073	u32 current_index =
7074		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
7075		CURRENT_STATE_INDEX_SHIFT;
7076
7077	if (current_index >= ps->performance_level_count) {
7078		return 0;
7079	} else {
7080		pl = &ps->performance_levels[current_index];
7081		return pl->mclk;
7082	}
7083}
7084