drm/radeon/kms: add dpm support for btc (v3)
[deliverable/linux.git] / drivers / gpu / drm / radeon / rv770_smc.c
1 /*
2 * Copyright 2011 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Alex Deucher
23 */
24
25 #include <linux/firmware.h>
26 #include "drmP.h"
27 #include "radeon.h"
28 #include "rv770d.h"
29 #include "rv770_dpm.h"
30 #include "rv770_smc.h"
31 #include "atom.h"
32 #include "radeon_ucode.h"
33
34 #define FIRST_SMC_INT_VECT_REG 0xFFD8
35 #define FIRST_INT_VECT_S19 0xFFC0
36
37 static const u8 rv770_smc_int_vectors[] =
38 {
39 0x08, 0x10, 0x08, 0x10,
40 0x08, 0x10, 0x08, 0x10,
41 0x08, 0x10, 0x08, 0x10,
42 0x08, 0x10, 0x08, 0x10,
43 0x08, 0x10, 0x08, 0x10,
44 0x08, 0x10, 0x08, 0x10,
45 0x08, 0x10, 0x08, 0x10,
46 0x08, 0x10, 0x08, 0x10,
47 0x08, 0x10, 0x08, 0x10,
48 0x08, 0x10, 0x08, 0x10,
49 0x08, 0x10, 0x08, 0x10,
50 0x08, 0x10, 0x08, 0x10,
51 0x08, 0x10, 0x0C, 0xD7,
52 0x08, 0x2B, 0x08, 0x10,
53 0x03, 0x51, 0x03, 0x51,
54 0x03, 0x51, 0x03, 0x51
55 };
56
57 static const u8 rv730_smc_int_vectors[] =
58 {
59 0x08, 0x15, 0x08, 0x15,
60 0x08, 0x15, 0x08, 0x15,
61 0x08, 0x15, 0x08, 0x15,
62 0x08, 0x15, 0x08, 0x15,
63 0x08, 0x15, 0x08, 0x15,
64 0x08, 0x15, 0x08, 0x15,
65 0x08, 0x15, 0x08, 0x15,
66 0x08, 0x15, 0x08, 0x15,
67 0x08, 0x15, 0x08, 0x15,
68 0x08, 0x15, 0x08, 0x15,
69 0x08, 0x15, 0x08, 0x15,
70 0x08, 0x15, 0x08, 0x15,
71 0x08, 0x15, 0x0C, 0xBB,
72 0x08, 0x30, 0x08, 0x15,
73 0x03, 0x56, 0x03, 0x56,
74 0x03, 0x56, 0x03, 0x56
75 };
76
77 static const u8 rv710_smc_int_vectors[] =
78 {
79 0x08, 0x04, 0x08, 0x04,
80 0x08, 0x04, 0x08, 0x04,
81 0x08, 0x04, 0x08, 0x04,
82 0x08, 0x04, 0x08, 0x04,
83 0x08, 0x04, 0x08, 0x04,
84 0x08, 0x04, 0x08, 0x04,
85 0x08, 0x04, 0x08, 0x04,
86 0x08, 0x04, 0x08, 0x04,
87 0x08, 0x04, 0x08, 0x04,
88 0x08, 0x04, 0x08, 0x04,
89 0x08, 0x04, 0x08, 0x04,
90 0x08, 0x04, 0x08, 0x04,
91 0x08, 0x04, 0x0C, 0xCB,
92 0x08, 0x1F, 0x08, 0x04,
93 0x03, 0x51, 0x03, 0x51,
94 0x03, 0x51, 0x03, 0x51
95 };
96
97 static const u8 rv740_smc_int_vectors[] =
98 {
99 0x08, 0x10, 0x08, 0x10,
100 0x08, 0x10, 0x08, 0x10,
101 0x08, 0x10, 0x08, 0x10,
102 0x08, 0x10, 0x08, 0x10,
103 0x08, 0x10, 0x08, 0x10,
104 0x08, 0x10, 0x08, 0x10,
105 0x08, 0x10, 0x08, 0x10,
106 0x08, 0x10, 0x08, 0x10,
107 0x08, 0x10, 0x08, 0x10,
108 0x08, 0x10, 0x08, 0x10,
109 0x08, 0x10, 0x08, 0x10,
110 0x08, 0x10, 0x08, 0x10,
111 0x08, 0x10, 0x0C, 0xD7,
112 0x08, 0x2B, 0x08, 0x10,
113 0x03, 0x51, 0x03, 0x51,
114 0x03, 0x51, 0x03, 0x51
115 };
116
117 static const u8 cedar_smc_int_vectors[] =
118 {
119 0x0B, 0x05, 0x0B, 0x05,
120 0x0B, 0x05, 0x0B, 0x05,
121 0x0B, 0x05, 0x0B, 0x05,
122 0x0B, 0x05, 0x0B, 0x05,
123 0x0B, 0x05, 0x0B, 0x05,
124 0x0B, 0x05, 0x0B, 0x05,
125 0x0B, 0x05, 0x0B, 0x05,
126 0x0B, 0x05, 0x0B, 0x05,
127 0x0B, 0x05, 0x0B, 0x05,
128 0x0B, 0x05, 0x0B, 0x05,
129 0x0B, 0x05, 0x0B, 0x05,
130 0x0B, 0x05, 0x0B, 0x05,
131 0x0B, 0x05, 0x11, 0x8B,
132 0x0B, 0x20, 0x0B, 0x05,
133 0x04, 0xF6, 0x04, 0xF6,
134 0x04, 0xF6, 0x04, 0xF6
135 };
136
137 static const u8 redwood_smc_int_vectors[] =
138 {
139 0x0B, 0x05, 0x0B, 0x05,
140 0x0B, 0x05, 0x0B, 0x05,
141 0x0B, 0x05, 0x0B, 0x05,
142 0x0B, 0x05, 0x0B, 0x05,
143 0x0B, 0x05, 0x0B, 0x05,
144 0x0B, 0x05, 0x0B, 0x05,
145 0x0B, 0x05, 0x0B, 0x05,
146 0x0B, 0x05, 0x0B, 0x05,
147 0x0B, 0x05, 0x0B, 0x05,
148 0x0B, 0x05, 0x0B, 0x05,
149 0x0B, 0x05, 0x0B, 0x05,
150 0x0B, 0x05, 0x0B, 0x05,
151 0x0B, 0x05, 0x11, 0x8B,
152 0x0B, 0x20, 0x0B, 0x05,
153 0x04, 0xF6, 0x04, 0xF6,
154 0x04, 0xF6, 0x04, 0xF6
155 };
156
157 static const u8 juniper_smc_int_vectors[] =
158 {
159 0x0B, 0x05, 0x0B, 0x05,
160 0x0B, 0x05, 0x0B, 0x05,
161 0x0B, 0x05, 0x0B, 0x05,
162 0x0B, 0x05, 0x0B, 0x05,
163 0x0B, 0x05, 0x0B, 0x05,
164 0x0B, 0x05, 0x0B, 0x05,
165 0x0B, 0x05, 0x0B, 0x05,
166 0x0B, 0x05, 0x0B, 0x05,
167 0x0B, 0x05, 0x0B, 0x05,
168 0x0B, 0x05, 0x0B, 0x05,
169 0x0B, 0x05, 0x0B, 0x05,
170 0x0B, 0x05, 0x0B, 0x05,
171 0x0B, 0x05, 0x11, 0x8B,
172 0x0B, 0x20, 0x0B, 0x05,
173 0x04, 0xF6, 0x04, 0xF6,
174 0x04, 0xF6, 0x04, 0xF6
175 };
176
177 static const u8 cypress_smc_int_vectors[] =
178 {
179 0x0B, 0x05, 0x0B, 0x05,
180 0x0B, 0x05, 0x0B, 0x05,
181 0x0B, 0x05, 0x0B, 0x05,
182 0x0B, 0x05, 0x0B, 0x05,
183 0x0B, 0x05, 0x0B, 0x05,
184 0x0B, 0x05, 0x0B, 0x05,
185 0x0B, 0x05, 0x0B, 0x05,
186 0x0B, 0x05, 0x0B, 0x05,
187 0x0B, 0x05, 0x0B, 0x05,
188 0x0B, 0x05, 0x0B, 0x05,
189 0x0B, 0x05, 0x0B, 0x05,
190 0x0B, 0x05, 0x0B, 0x05,
191 0x0B, 0x05, 0x11, 0x8B,
192 0x0B, 0x20, 0x0B, 0x05,
193 0x04, 0xF6, 0x04, 0xF6,
194 0x04, 0xF6, 0x04, 0xF6
195 };
196
197 static const u8 barts_smc_int_vectors[] =
198 {
199 0x0C, 0x14, 0x0C, 0x14,
200 0x0C, 0x14, 0x0C, 0x14,
201 0x0C, 0x14, 0x0C, 0x14,
202 0x0C, 0x14, 0x0C, 0x14,
203 0x0C, 0x14, 0x0C, 0x14,
204 0x0C, 0x14, 0x0C, 0x14,
205 0x0C, 0x14, 0x0C, 0x14,
206 0x0C, 0x14, 0x0C, 0x14,
207 0x0C, 0x14, 0x0C, 0x14,
208 0x0C, 0x14, 0x0C, 0x14,
209 0x0C, 0x14, 0x0C, 0x14,
210 0x0C, 0x14, 0x0C, 0x14,
211 0x0C, 0x14, 0x12, 0xAA,
212 0x0C, 0x2F, 0x15, 0xF6,
213 0x15, 0xF6, 0x05, 0x0A,
214 0x05, 0x0A, 0x05, 0x0A
215 };
216
217 static const u8 turks_smc_int_vectors[] =
218 {
219 0x0C, 0x14, 0x0C, 0x14,
220 0x0C, 0x14, 0x0C, 0x14,
221 0x0C, 0x14, 0x0C, 0x14,
222 0x0C, 0x14, 0x0C, 0x14,
223 0x0C, 0x14, 0x0C, 0x14,
224 0x0C, 0x14, 0x0C, 0x14,
225 0x0C, 0x14, 0x0C, 0x14,
226 0x0C, 0x14, 0x0C, 0x14,
227 0x0C, 0x14, 0x0C, 0x14,
228 0x0C, 0x14, 0x0C, 0x14,
229 0x0C, 0x14, 0x0C, 0x14,
230 0x0C, 0x14, 0x0C, 0x14,
231 0x0C, 0x14, 0x12, 0xAA,
232 0x0C, 0x2F, 0x15, 0xF6,
233 0x15, 0xF6, 0x05, 0x0A,
234 0x05, 0x0A, 0x05, 0x0A
235 };
236
237 static const u8 caicos_smc_int_vectors[] =
238 {
239 0x0C, 0x14, 0x0C, 0x14,
240 0x0C, 0x14, 0x0C, 0x14,
241 0x0C, 0x14, 0x0C, 0x14,
242 0x0C, 0x14, 0x0C, 0x14,
243 0x0C, 0x14, 0x0C, 0x14,
244 0x0C, 0x14, 0x0C, 0x14,
245 0x0C, 0x14, 0x0C, 0x14,
246 0x0C, 0x14, 0x0C, 0x14,
247 0x0C, 0x14, 0x0C, 0x14,
248 0x0C, 0x14, 0x0C, 0x14,
249 0x0C, 0x14, 0x0C, 0x14,
250 0x0C, 0x14, 0x0C, 0x14,
251 0x0C, 0x14, 0x12, 0xAA,
252 0x0C, 0x2F, 0x15, 0xF6,
253 0x15, 0xF6, 0x05, 0x0A,
254 0x05, 0x0A, 0x05, 0x0A
255 };
256
257 int rv770_set_smc_sram_address(struct radeon_device *rdev,
258 u16 smc_address, u16 limit)
259 {
260 u32 addr;
261
262 if (smc_address & 3)
263 return -EINVAL;
264 if ((smc_address + 3) > limit)
265 return -EINVAL;
266
267 addr = smc_address;
268 addr |= SMC_SRAM_AUTO_INC_DIS;
269
270 WREG32(SMC_SRAM_ADDR, addr);
271
272 return 0;
273 }
274
275 int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
276 u16 smc_start_address, const u8 *src,
277 u16 byte_count, u16 limit)
278 {
279 u32 data, original_data, extra_shift;
280 u16 addr;
281 int ret;
282
283 if (smc_start_address & 3)
284 return -EINVAL;
285 if ((smc_start_address + byte_count) > limit)
286 return -EINVAL;
287
288 addr = smc_start_address;
289
290 while (byte_count >= 4) {
291 /* SMC address space is BE */
292 data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
293
294 ret = rv770_set_smc_sram_address(rdev, addr, limit);
295 if (ret)
296 return ret;
297
298 WREG32(SMC_SRAM_DATA, data);
299
300 src += 4;
301 byte_count -= 4;
302 addr += 4;
303 }
304
305 /* RMW for final bytes */
306 if (byte_count > 0) {
307 data = 0;
308
309 ret = rv770_set_smc_sram_address(rdev, addr, limit);
310 if (ret)
311 return ret;
312
313 original_data = RREG32(SMC_SRAM_DATA);
314
315 extra_shift = 8 * (4 - byte_count);
316
317 while (byte_count > 0) {
318 /* SMC address space is BE */
319 data = (data << 8) + *src++;
320 byte_count--;
321 }
322
323 data <<= extra_shift;
324
325 data |= (original_data & ~((~0UL) << extra_shift));
326
327 ret = rv770_set_smc_sram_address(rdev, addr, limit);
328 if (ret)
329 return ret;
330
331 WREG32(SMC_SRAM_DATA, data);
332 }
333
334 return 0;
335 }
336
337 static int rv770_program_interrupt_vectors(struct radeon_device *rdev,
338 u32 smc_first_vector, const u8 *src,
339 u32 byte_count)
340 {
341 u32 tmp, i;
342
343 if (byte_count % 4)
344 return -EINVAL;
345
346 if (smc_first_vector < FIRST_SMC_INT_VECT_REG) {
347 tmp = FIRST_SMC_INT_VECT_REG - smc_first_vector;
348
349 if (tmp > byte_count)
350 return 0;
351
352 byte_count -= tmp;
353 src += tmp;
354 smc_first_vector = FIRST_SMC_INT_VECT_REG;
355 }
356
357 for (i = 0; i < byte_count; i += 4) {
358 /* SMC address space is BE */
359 tmp = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3];
360
361 WREG32(SMC_ISR_FFD8_FFDB + i, tmp);
362 }
363
364 return 0;
365 }
366
367 void rv770_start_smc(struct radeon_device *rdev)
368 {
369 WREG32_P(SMC_IO, SMC_RST_N, ~SMC_RST_N);
370 }
371
372 void rv770_reset_smc(struct radeon_device *rdev)
373 {
374 WREG32_P(SMC_IO, 0, ~SMC_RST_N);
375 }
376
377 void rv770_stop_smc_clock(struct radeon_device *rdev)
378 {
379 WREG32_P(SMC_IO, 0, ~SMC_CLK_EN);
380 }
381
382 void rv770_start_smc_clock(struct radeon_device *rdev)
383 {
384 WREG32_P(SMC_IO, SMC_CLK_EN, ~SMC_CLK_EN);
385 }
386
387 bool rv770_is_smc_running(struct radeon_device *rdev)
388 {
389 u32 tmp;
390
391 tmp = RREG32(SMC_IO);
392
393 if ((tmp & SMC_RST_N) && (tmp & SMC_CLK_EN))
394 return true;
395 else
396 return false;
397 }
398
399 PPSMC_Result rv770_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg)
400 {
401 u32 tmp;
402 int i;
403 PPSMC_Result result;
404
405 if (!rv770_is_smc_running(rdev))
406 return PPSMC_Result_Failed;
407
408 WREG32_P(SMC_MSG, HOST_SMC_MSG(msg), ~HOST_SMC_MSG_MASK);
409
410 for (i = 0; i < rdev->usec_timeout; i++) {
411 tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK;
412 tmp >>= HOST_SMC_RESP_SHIFT;
413 if (tmp != 0)
414 break;
415 udelay(1);
416 }
417
418 tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK;
419 tmp >>= HOST_SMC_RESP_SHIFT;
420
421 result = (PPSMC_Result)tmp;
422 return result;
423 }
424
425 PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev)
426 {
427 int i;
428 PPSMC_Result result = PPSMC_Result_OK;
429
430 if (!rv770_is_smc_running(rdev))
431 return result;
432
433 for (i = 0; i < rdev->usec_timeout; i++) {
434 if (RREG32(SMC_IO) & SMC_STOP_MODE)
435 break;
436 udelay(1);
437 }
438
439 return result;
440 }
441
442 static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit)
443 {
444 u16 i;
445
446 for (i = 0; i < limit; i += 4) {
447 rv770_set_smc_sram_address(rdev, i, limit);
448 WREG32(SMC_SRAM_DATA, 0);
449 }
450 }
451
452 int rv770_load_smc_ucode(struct radeon_device *rdev,
453 u16 limit)
454 {
455 int ret;
456 const u8 *int_vect;
457 u16 int_vect_start_address;
458 u16 int_vect_size;
459 const u8 *ucode_data;
460 u16 ucode_start_address;
461 u16 ucode_size;
462
463 if (!rdev->smc_fw)
464 return -EINVAL;
465
466 rv770_clear_smc_sram(rdev, limit);
467
468 switch (rdev->family) {
469 case CHIP_RV770:
470 ucode_start_address = RV770_SMC_UCODE_START;
471 ucode_size = RV770_SMC_UCODE_SIZE;
472 int_vect = (const u8 *)&rv770_smc_int_vectors;
473 int_vect_start_address = RV770_SMC_INT_VECTOR_START;
474 int_vect_size = RV770_SMC_INT_VECTOR_SIZE;
475 break;
476 case CHIP_RV730:
477 ucode_start_address = RV730_SMC_UCODE_START;
478 ucode_size = RV730_SMC_UCODE_SIZE;
479 int_vect = (const u8 *)&rv730_smc_int_vectors;
480 int_vect_start_address = RV730_SMC_INT_VECTOR_START;
481 int_vect_size = RV730_SMC_INT_VECTOR_SIZE;
482 break;
483 case CHIP_RV710:
484 ucode_start_address = RV710_SMC_UCODE_START;
485 ucode_size = RV710_SMC_UCODE_SIZE;
486 int_vect = (const u8 *)&rv710_smc_int_vectors;
487 int_vect_start_address = RV710_SMC_INT_VECTOR_START;
488 int_vect_size = RV710_SMC_INT_VECTOR_SIZE;
489 break;
490 case CHIP_RV740:
491 ucode_start_address = RV740_SMC_UCODE_START;
492 ucode_size = RV740_SMC_UCODE_SIZE;
493 int_vect = (const u8 *)&rv740_smc_int_vectors;
494 int_vect_start_address = RV740_SMC_INT_VECTOR_START;
495 int_vect_size = RV740_SMC_INT_VECTOR_SIZE;
496 break;
497 case CHIP_CEDAR:
498 ucode_start_address = CEDAR_SMC_UCODE_START;
499 ucode_size = CEDAR_SMC_UCODE_SIZE;
500 int_vect = (const u8 *)&cedar_smc_int_vectors;
501 int_vect_start_address = CEDAR_SMC_INT_VECTOR_START;
502 int_vect_size = CEDAR_SMC_INT_VECTOR_SIZE;
503 break;
504 case CHIP_REDWOOD:
505 ucode_start_address = REDWOOD_SMC_UCODE_START;
506 ucode_size = REDWOOD_SMC_UCODE_SIZE;
507 int_vect = (const u8 *)&redwood_smc_int_vectors;
508 int_vect_start_address = REDWOOD_SMC_INT_VECTOR_START;
509 int_vect_size = REDWOOD_SMC_INT_VECTOR_SIZE;
510 break;
511 case CHIP_JUNIPER:
512 ucode_start_address = JUNIPER_SMC_UCODE_START;
513 ucode_size = JUNIPER_SMC_UCODE_SIZE;
514 int_vect = (const u8 *)&juniper_smc_int_vectors;
515 int_vect_start_address = JUNIPER_SMC_INT_VECTOR_START;
516 int_vect_size = JUNIPER_SMC_INT_VECTOR_SIZE;
517 break;
518 case CHIP_CYPRESS:
519 case CHIP_HEMLOCK:
520 ucode_start_address = CYPRESS_SMC_UCODE_START;
521 ucode_size = CYPRESS_SMC_UCODE_SIZE;
522 int_vect = (const u8 *)&cypress_smc_int_vectors;
523 int_vect_start_address = CYPRESS_SMC_INT_VECTOR_START;
524 int_vect_size = CYPRESS_SMC_INT_VECTOR_SIZE;
525 break;
526 case CHIP_BARTS:
527 ucode_start_address = BARTS_SMC_UCODE_START;
528 ucode_size = BARTS_SMC_UCODE_SIZE;
529 int_vect = (const u8 *)&barts_smc_int_vectors;
530 int_vect_start_address = BARTS_SMC_INT_VECTOR_START;
531 int_vect_size = BARTS_SMC_INT_VECTOR_SIZE;
532 break;
533 case CHIP_TURKS:
534 ucode_start_address = TURKS_SMC_UCODE_START;
535 ucode_size = TURKS_SMC_UCODE_SIZE;
536 int_vect = (const u8 *)&turks_smc_int_vectors;
537 int_vect_start_address = TURKS_SMC_INT_VECTOR_START;
538 int_vect_size = TURKS_SMC_INT_VECTOR_SIZE;
539 break;
540 case CHIP_CAICOS:
541 ucode_start_address = CAICOS_SMC_UCODE_START;
542 ucode_size = CAICOS_SMC_UCODE_SIZE;
543 int_vect = (const u8 *)&caicos_smc_int_vectors;
544 int_vect_start_address = CAICOS_SMC_INT_VECTOR_START;
545 int_vect_size = CAICOS_SMC_INT_VECTOR_SIZE;
546 break;
547 default:
548 DRM_ERROR("unknown asic in smc ucode loader\n");
549 BUG();
550 }
551
552 /* load the ucode */
553 ucode_data = (const u8 *)rdev->smc_fw->data;
554 ret = rv770_copy_bytes_to_smc(rdev, ucode_start_address,
555 ucode_data, ucode_size, limit);
556 if (ret)
557 return ret;
558
559 /* set up the int vectors */
560 ret = rv770_program_interrupt_vectors(rdev, int_vect_start_address,
561 int_vect, int_vect_size);
562 if (ret)
563 return ret;
564
565 return 0;
566 }
567
568 int rv770_read_smc_sram_dword(struct radeon_device *rdev,
569 u16 smc_address, u32 *value, u16 limit)
570 {
571 int ret;
572
573 ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
574 if (ret)
575 return ret;
576
577 *value = RREG32(SMC_SRAM_DATA);
578
579 return 0;
580 }
581
582 int rv770_write_smc_sram_dword(struct radeon_device *rdev,
583 u16 smc_address, u32 value, u16 limit)
584 {
585 int ret;
586
587 ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
588 if (ret)
589 return ret;
590
591 WREG32(SMC_SRAM_DATA, value);
592
593 return 0;
594 }
This page took 0.045208 seconds and 5 git commands to generate.