Merge branch 'master' into queue
[linux-2.6-microblaze.git] / drivers / gpu / drm / nouveau / nouveau_mem.c
1 /*
2  * Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3  * Copyright 2005 Stephane Marchesin
4  *
5  * The Weather Channel (TM) funded Tungsten Graphics to develop the
6  * initial release of the Radeon 8500 driver under the XFree86 license.
7  * This notice must be preserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice (including the next
17  * paragraph) shall be included in all copies or substantial portions of the
18  * Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23  * THE AUTHORS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  *
28  * Authors:
29  *    Ben Skeggs <bskeggs@redhat.com>
30  *    Roy Spliet <r.spliet@student.tudelft.nl>
31  */
32
33 #include "nouveau_drm.h"
34 #include "nouveau_pm.h"
35
36 #include <subdev/fb.h>
37
38 static int
39 nv40_mem_timing_calc(struct drm_device *dev, u32 freq,
40                      struct nouveau_pm_tbl_entry *e, u8 len,
41                      struct nouveau_pm_memtiming *boot,
42                      struct nouveau_pm_memtiming *t)
43 {
44         struct nouveau_drm *drm = nouveau_drm(dev);
45
46         t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC);
47
48         /* XXX: I don't trust the -1's and +1's... they must come
49          *      from somewhere! */
50         t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 |
51                     1 << 16 |
52                     (e->tWTR + 2 + (t->tCWL - 1)) << 8 |
53                     (e->tCL + 2 - (t->tCWL - 1));
54
55         t->reg[2] = 0x20200000 |
56                     ((t->tCWL - 1) << 24 |
57                      e->tRRD << 16 |
58                      e->tRCDWR << 8 |
59                      e->tRCDRD);
60
61         NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x\n", t->id,
62                  t->reg[0], t->reg[1], t->reg[2]);
63         return 0;
64 }
65
66 static int
67 nv50_mem_timing_calc(struct drm_device *dev, u32 freq,
68                      struct nouveau_pm_tbl_entry *e, u8 len,
69                      struct nouveau_pm_memtiming *boot,
70                      struct nouveau_pm_memtiming *t)
71 {
72         struct nouveau_device *device = nouveau_dev(dev);
73         struct nouveau_fb *pfb = nouveau_fb(device);
74         struct nouveau_drm *drm = nouveau_drm(dev);
75         struct bit_entry P;
76         uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3;
77
78         if (bit_table(dev, 'P', &P))
79                 return -EINVAL;
80
81         switch (min(len, (u8) 22)) {
82         case 22:
83                 unk21 = e->tUNK_21;
84         case 21:
85                 unk20 = e->tUNK_20;
86         case 20:
87                 if (e->tCWL > 0)
88                         t->tCWL = e->tCWL;
89         case 19:
90                 unk18 = e->tUNK_18;
91                 break;
92         }
93
94         t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC);
95
96         t->reg[1] = (e->tWR + 2 + (t->tCWL - 1)) << 24 |
97                                 max(unk18, (u8) 1) << 16 |
98                                 (e->tWTR + 2 + (t->tCWL - 1)) << 8;
99
100         t->reg[2] = ((t->tCWL - 1) << 24 |
101                     e->tRRD << 16 |
102                     e->tRCDWR << 8 |
103                     e->tRCDRD);
104
105         t->reg[4] = e->tUNK_13 << 8  | e->tUNK_13;
106
107         t->reg[5] = (e->tRFC << 24 | max(e->tRCDRD, e->tRCDWR) << 16 | e->tRP);
108
109         t->reg[8] = boot->reg[8] & 0xffffff00;
110
111         if (P.version == 1) {
112                 t->reg[1] |= (e->tCL + 2 - (t->tCWL - 1));
113
114                 t->reg[3] = (0x14 + e->tCL) << 24 |
115                             0x16 << 16 |
116                             (e->tCL - 1) << 8 |
117                             (e->tCL - 1);
118
119                 t->reg[4] |= boot->reg[4] & 0xffff0000;
120
121                 t->reg[6] = (0x33 - t->tCWL) << 16 |
122                             t->tCWL << 8 |
123                             (0x2e + e->tCL - t->tCWL);
124
125                 t->reg[7] = 0x4000202 | (e->tCL - 1) << 16;
126
127                 /* XXX: P.version == 1 only has DDR2 and GDDR3? */
128                 if (pfb->ram.type == NV_MEM_TYPE_DDR2) {
129                         t->reg[5] |= (e->tCL + 3) << 8;
130                         t->reg[6] |= (t->tCWL - 2) << 8;
131                         t->reg[8] |= (e->tCL - 4);
132                 } else {
133                         t->reg[5] |= (e->tCL + 2) << 8;
134                         t->reg[6] |= t->tCWL << 8;
135                         t->reg[8] |= (e->tCL - 2);
136                 }
137         } else {
138                 t->reg[1] |= (5 + e->tCL - (t->tCWL));
139
140                 /* XXX: 0xb? 0x30? */
141                 t->reg[3] = (0x30 + e->tCL) << 24 |
142                             (boot->reg[3] & 0x00ff0000)|
143                             (0xb + e->tCL) << 8 |
144                             (e->tCL - 1);
145
146                 t->reg[4] |= (unk20 << 24 | unk21 << 16);
147
148                 /* XXX: +6? */
149                 t->reg[5] |= (t->tCWL + 6) << 8;
150
151                 t->reg[6] = (0x5a + e->tCL) << 16 |
152                             (6 - e->tCL + t->tCWL) << 8 |
153                             (0x50 + e->tCL - t->tCWL);
154
155                 tmp7_3 = (boot->reg[7] & 0xff000000) >> 24;
156                 t->reg[7] = (tmp7_3 << 24) |
157                             ((tmp7_3 - 6 + e->tCL) << 16) |
158                             0x202;
159         }
160
161         NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x %08x\n", t->id,
162                  t->reg[0], t->reg[1], t->reg[2], t->reg[3]);
163         NV_DEBUG(drm, "         230: %08x %08x %08x %08x\n",
164                  t->reg[4], t->reg[5], t->reg[6], t->reg[7]);
165         NV_DEBUG(drm, "         240: %08x\n", t->reg[8]);
166         return 0;
167 }
168
169 static int
170 nvc0_mem_timing_calc(struct drm_device *dev, u32 freq,
171                      struct nouveau_pm_tbl_entry *e, u8 len,
172                      struct nouveau_pm_memtiming *boot,
173                      struct nouveau_pm_memtiming *t)
174 {
175         struct nouveau_drm *drm = nouveau_drm(dev);
176
177         if (e->tCWL > 0)
178                 t->tCWL = e->tCWL;
179
180         t->reg[0] = (e->tRP << 24 | (e->tRAS & 0x7f) << 17 |
181                      e->tRFC << 8 | e->tRC);
182
183         t->reg[1] = (boot->reg[1] & 0xff000000) |
184                     (e->tRCDWR & 0x0f) << 20 |
185                     (e->tRCDRD & 0x0f) << 14 |
186                     (t->tCWL << 7) |
187                     (e->tCL & 0x0f);
188
189         t->reg[2] = (boot->reg[2] & 0xff0000ff) |
190                     e->tWR << 16 | e->tWTR << 8;
191
192         t->reg[3] = (e->tUNK_20 & 0x1f) << 9 |
193                     (e->tUNK_21 & 0xf) << 5 |
194                     (e->tUNK_13 & 0x1f);
195
196         t->reg[4] = (boot->reg[4] & 0xfff00fff) |
197                     (e->tRRD&0x1f) << 15;
198
199         NV_DEBUG(drm, "Entry %d: 290: %08x %08x %08x %08x\n", t->id,
200                  t->reg[0], t->reg[1], t->reg[2], t->reg[3]);
201         NV_DEBUG(drm, "         2a0: %08x\n", t->reg[4]);
202         return 0;
203 }
204
205 /**
206  * MR generation methods
207  */
208
209 static int
210 nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq,
211                     struct nouveau_pm_tbl_entry *e, u8 len,
212                     struct nouveau_pm_memtiming *boot,
213                     struct nouveau_pm_memtiming *t)
214 {
215         struct nouveau_drm *drm = nouveau_drm(dev);
216
217         t->drive_strength = 0;
218         if (len < 15) {
219                 t->odt = boot->odt;
220         } else {
221                 t->odt = e->RAM_FT1 & 0x07;
222         }
223
224         if (e->tCL >= NV_MEM_CL_DDR2_MAX) {
225                 NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL);
226                 return -ERANGE;
227         }
228
229         if (e->tWR >= NV_MEM_WR_DDR2_MAX) {
230                 NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR);
231                 return -ERANGE;
232         }
233
234         if (t->odt > 3) {
235                 NV_WARN(drm, "(%u) Invalid odt value, assuming disabled: %x",
236                         t->id, t->odt);
237                 t->odt = 0;
238         }
239
240         t->mr[0] = (boot->mr[0] & 0x100f) |
241                    (e->tCL) << 4 |
242                    (e->tWR - 1) << 9;
243         t->mr[1] = (boot->mr[1] & 0x101fbb) |
244                    (t->odt & 0x1) << 2 |
245                    (t->odt & 0x2) << 5;
246
247         NV_DEBUG(drm, "(%u) MR: %08x", t->id, t->mr[0]);
248         return 0;
249 }
250
251 static const uint8_t nv_mem_wr_lut_ddr3[NV_MEM_WR_DDR3_MAX] = {
252         0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
253
254 static int
255 nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq,
256                     struct nouveau_pm_tbl_entry *e, u8 len,
257                     struct nouveau_pm_memtiming *boot,
258                     struct nouveau_pm_memtiming *t)
259 {
260         struct nouveau_drm *drm = nouveau_drm(dev);
261         u8 cl = e->tCL - 4;
262
263         t->drive_strength = 0;
264         if (len < 15) {
265                 t->odt = boot->odt;
266         } else {
267                 t->odt = e->RAM_FT1 & 0x07;
268         }
269
270         if (e->tCL >= NV_MEM_CL_DDR3_MAX || e->tCL < 4) {
271                 NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL);
272                 return -ERANGE;
273         }
274
275         if (e->tWR >= NV_MEM_WR_DDR3_MAX || e->tWR < 4) {
276                 NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR);
277                 return -ERANGE;
278         }
279
280         if (e->tCWL < 5) {
281                 NV_WARN(drm, "(%u) Invalid tCWL: %u", t->id, e->tCWL);
282                 return -ERANGE;
283         }
284
285         t->mr[0] = (boot->mr[0] & 0x180b) |
286                    /* CAS */
287                    (cl & 0x7) << 4 |
288                    (cl & 0x8) >> 1 |
289                    (nv_mem_wr_lut_ddr3[e->tWR]) << 9;
290         t->mr[1] = (boot->mr[1] & 0x101dbb) |
291                    (t->odt & 0x1) << 2 |
292                    (t->odt & 0x2) << 5 |
293                    (t->odt & 0x4) << 7;
294         t->mr[2] = (boot->mr[2] & 0x20ffb7) | (e->tCWL - 5) << 3;
295
296         NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]);
297         return 0;
298 }
299
300 static const uint8_t nv_mem_cl_lut_gddr3[NV_MEM_CL_GDDR3_MAX] = {
301         0, 0, 0, 0, 4, 5, 6, 7, 0, 1, 2, 3, 8, 9, 10, 11};
302 static const uint8_t nv_mem_wr_lut_gddr3[NV_MEM_WR_GDDR3_MAX] = {
303         0, 0, 0, 0, 0, 2, 3, 8, 9, 10, 11, 0, 0, 1, 1, 0, 3};
304
305 static int
306 nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq,
307                      struct nouveau_pm_tbl_entry *e, u8 len,
308                      struct nouveau_pm_memtiming *boot,
309                      struct nouveau_pm_memtiming *t)
310 {
311         struct nouveau_drm *drm = nouveau_drm(dev);
312
313         if (len < 15) {
314                 t->drive_strength = boot->drive_strength;
315                 t->odt = boot->odt;
316         } else {
317                 t->drive_strength = (e->RAM_FT1 & 0x30) >> 4;
318                 t->odt = e->RAM_FT1 & 0x07;
319         }
320
321         if (e->tCL >= NV_MEM_CL_GDDR3_MAX) {
322                 NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL);
323                 return -ERANGE;
324         }
325
326         if (e->tWR >= NV_MEM_WR_GDDR3_MAX) {
327                 NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR);
328                 return -ERANGE;
329         }
330
331         if (t->odt > 3) {
332                 NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x",
333                         t->id, t->odt);
334                 t->odt = 0;
335         }
336
337         t->mr[0] = (boot->mr[0] & 0xe0b) |
338                    /* CAS */
339                    ((nv_mem_cl_lut_gddr3[e->tCL] & 0x7) << 4) |
340                    ((nv_mem_cl_lut_gddr3[e->tCL] & 0x8) >> 2);
341         t->mr[1] = (boot->mr[1] & 0x100f40) | t->drive_strength |
342                    (t->odt << 2) |
343                    (nv_mem_wr_lut_gddr3[e->tWR] & 0xf) << 4;
344         t->mr[2] = boot->mr[2];
345
346         NV_DEBUG(drm, "(%u) MR: %08x %08x %08x", t->id,
347                       t->mr[0], t->mr[1], t->mr[2]);
348         return 0;
349 }
350
351 static int
352 nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq,
353                      struct nouveau_pm_tbl_entry *e, u8 len,
354                      struct nouveau_pm_memtiming *boot,
355                      struct nouveau_pm_memtiming *t)
356 {
357         struct nouveau_drm *drm = nouveau_drm(dev);
358
359         if (len < 15) {
360                 t->drive_strength = boot->drive_strength;
361                 t->odt = boot->odt;
362         } else {
363                 t->drive_strength = (e->RAM_FT1 & 0x30) >> 4;
364                 t->odt = e->RAM_FT1 & 0x03;
365         }
366
367         if (e->tCL >= NV_MEM_CL_GDDR5_MAX) {
368                 NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL);
369                 return -ERANGE;
370         }
371
372         if (e->tWR >= NV_MEM_WR_GDDR5_MAX) {
373                 NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR);
374                 return -ERANGE;
375         }
376
377         if (t->odt > 3) {
378                 NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x",
379                         t->id, t->odt);
380                 t->odt = 0;
381         }
382
383         t->mr[0] = (boot->mr[0] & 0x007) |
384                    ((e->tCL - 5) << 3) |
385                    ((e->tWR - 4) << 8);
386         t->mr[1] = (boot->mr[1] & 0x1007f0) |
387                    t->drive_strength |
388                    (t->odt << 2);
389
390         NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]);
391         return 0;
392 }
393
394 int
395 nouveau_mem_timing_calc(struct drm_device *dev, u32 freq,
396                         struct nouveau_pm_memtiming *t)
397 {
398         struct nouveau_device *device = nouveau_dev(dev);
399         struct nouveau_fb *pfb = nouveau_fb(device);
400         struct nouveau_pm *pm = nouveau_pm(dev);
401         struct nouveau_pm_memtiming *boot = &pm->boot.timing;
402         struct nouveau_pm_tbl_entry *e;
403         u8 ver, len, *ptr, *ramcfg;
404         int ret;
405
406         ptr = nouveau_perf_timing(dev, freq, &ver, &len);
407         if (!ptr || ptr[0] == 0x00) {
408                 *t = *boot;
409                 return 0;
410         }
411         e = (struct nouveau_pm_tbl_entry *)ptr;
412
413         t->tCWL = boot->tCWL;
414
415         switch (device->card_type) {
416         case NV_40:
417                 ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t);
418                 break;
419         case NV_50:
420                 ret = nv50_mem_timing_calc(dev, freq, e, len, boot, t);
421                 break;
422         case NV_C0:
423         case NV_D0:
424                 ret = nvc0_mem_timing_calc(dev, freq, e, len, boot, t);
425                 break;
426         default:
427                 ret = -ENODEV;
428                 break;
429         }
430
431         switch (pfb->ram.type * !ret) {
432         case NV_MEM_TYPE_GDDR3:
433                 ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t);
434                 break;
435         case NV_MEM_TYPE_GDDR5:
436                 ret = nouveau_mem_gddr5_mr(dev, freq, e, len, boot, t);
437                 break;
438         case NV_MEM_TYPE_DDR2:
439                 ret = nouveau_mem_ddr2_mr(dev, freq, e, len, boot, t);
440                 break;
441         case NV_MEM_TYPE_DDR3:
442                 ret = nouveau_mem_ddr3_mr(dev, freq, e, len, boot, t);
443                 break;
444         default:
445                 ret = -EINVAL;
446                 break;
447         }
448
449         ramcfg = nouveau_perf_ramcfg(dev, freq, &ver, &len);
450         if (ramcfg) {
451                 int dll_off;
452
453                 if (ver == 0x00)
454                         dll_off = !!(ramcfg[3] & 0x04);
455                 else
456                         dll_off = !!(ramcfg[2] & 0x40);
457
458                 switch (pfb->ram.type) {
459                 case NV_MEM_TYPE_GDDR3:
460                         t->mr[1] &= ~0x00000040;
461                         t->mr[1] |=  0x00000040 * dll_off;
462                         break;
463                 default:
464                         t->mr[1] &= ~0x00000001;
465                         t->mr[1] |=  0x00000001 * dll_off;
466                         break;
467                 }
468         }
469
470         return ret;
471 }
472
473 void
474 nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t)
475 {
476         struct nouveau_device *device = nouveau_dev(dev);
477         struct nouveau_fb *pfb = nouveau_fb(device);
478         u32 timing_base, timing_regs, mr_base;
479         int i;
480
481         if (device->card_type >= 0xC0) {
482                 timing_base = 0x10f290;
483                 mr_base = 0x10f300;
484         } else {
485                 timing_base = 0x100220;
486                 mr_base = 0x1002c0;
487         }
488
489         t->id = -1;
490
491         switch (device->card_type) {
492         case NV_50:
493                 timing_regs = 9;
494                 break;
495         case NV_C0:
496         case NV_D0:
497                 timing_regs = 5;
498                 break;
499         case NV_30:
500         case NV_40:
501                 timing_regs = 3;
502                 break;
503         default:
504                 timing_regs = 0;
505                 return;
506         }
507         for(i = 0; i < timing_regs; i++)
508                 t->reg[i] = nv_rd32(device, timing_base + (0x04 * i));
509
510         t->tCWL = 0;
511         if (device->card_type < NV_C0) {
512                 t->tCWL = ((nv_rd32(device, 0x100228) & 0x0f000000) >> 24) + 1;
513         } else if (device->card_type <= NV_D0) {
514                 t->tCWL = ((nv_rd32(device, 0x10f294) & 0x00000f80) >> 7);
515         }
516
517         t->mr[0] = nv_rd32(device, mr_base);
518         t->mr[1] = nv_rd32(device, mr_base + 0x04);
519         t->mr[2] = nv_rd32(device, mr_base + 0x20);
520         t->mr[3] = nv_rd32(device, mr_base + 0x24);
521
522         t->odt = 0;
523         t->drive_strength = 0;
524
525         switch (pfb->ram.type) {
526         case NV_MEM_TYPE_DDR3:
527                 t->odt |= (t->mr[1] & 0x200) >> 7;
528         case NV_MEM_TYPE_DDR2:
529                 t->odt |= (t->mr[1] & 0x04) >> 2 |
530                           (t->mr[1] & 0x40) >> 5;
531                 break;
532         case NV_MEM_TYPE_GDDR3:
533         case NV_MEM_TYPE_GDDR5:
534                 t->drive_strength = t->mr[1] & 0x03;
535                 t->odt = (t->mr[1] & 0x0c) >> 2;
536                 break;
537         default:
538                 break;
539         }
540 }
541
542 int
543 nouveau_mem_exec(struct nouveau_mem_exec_func *exec,
544                  struct nouveau_pm_level *perflvl)
545 {
546         struct nouveau_drm *drm = nouveau_drm(exec->dev);
547         struct nouveau_device *device = nouveau_dev(exec->dev);
548         struct nouveau_fb *pfb = nouveau_fb(device);
549         struct nouveau_pm_memtiming *info = &perflvl->timing;
550         u32 tMRD = 1000, tCKSRE = 0, tCKSRX = 0, tXS = 0, tDLLK = 0;
551         u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] };
552         u32 mr1_dlloff;
553
554         switch (pfb->ram.type) {
555         case NV_MEM_TYPE_DDR2:
556                 tDLLK = 2000;
557                 mr1_dlloff = 0x00000001;
558                 break;
559         case NV_MEM_TYPE_DDR3:
560                 tDLLK = 12000;
561                 tCKSRE = 2000;
562                 tXS = 1000;
563                 mr1_dlloff = 0x00000001;
564                 break;
565         case NV_MEM_TYPE_GDDR3:
566                 tDLLK = 40000;
567                 mr1_dlloff = 0x00000040;
568                 break;
569         default:
570                 NV_ERROR(drm, "cannot reclock unsupported memtype\n");
571                 return -ENODEV;
572         }
573
574         /* fetch current MRs */
575         switch (pfb->ram.type) {
576         case NV_MEM_TYPE_GDDR3:
577         case NV_MEM_TYPE_DDR3:
578                 mr[2] = exec->mrg(exec, 2);
579         default:
580                 mr[1] = exec->mrg(exec, 1);
581                 mr[0] = exec->mrg(exec, 0);
582                 break;
583         }
584
585         /* DLL 'on' -> DLL 'off' mode, disable before entering self-refresh  */
586         if (!(mr[1] & mr1_dlloff) && (info->mr[1] & mr1_dlloff)) {
587                 exec->precharge(exec);
588                 exec->mrs (exec, 1, mr[1] | mr1_dlloff);
589                 exec->wait(exec, tMRD);
590         }
591
592         /* enter self-refresh mode */
593         exec->precharge(exec);
594         exec->refresh(exec);
595         exec->refresh(exec);
596         exec->refresh_auto(exec, false);
597         exec->refresh_self(exec, true);
598         exec->wait(exec, tCKSRE);
599
600         /* modify input clock frequency */
601         exec->clock_set(exec);
602
603         /* exit self-refresh mode */
604         exec->wait(exec, tCKSRX);
605         exec->precharge(exec);
606         exec->refresh_self(exec, false);
607         exec->refresh_auto(exec, true);
608         exec->wait(exec, tXS);
609         exec->wait(exec, tXS);
610
611         /* update MRs */
612         if (mr[2] != info->mr[2]) {
613                 exec->mrs (exec, 2, info->mr[2]);
614                 exec->wait(exec, tMRD);
615         }
616
617         if (mr[1] != info->mr[1]) {
618                 /* need to keep DLL off until later, at least on GDDR3 */
619                 exec->mrs (exec, 1, info->mr[1] | (mr[1] & mr1_dlloff));
620                 exec->wait(exec, tMRD);
621         }
622
623         if (mr[0] != info->mr[0]) {
624                 exec->mrs (exec, 0, info->mr[0]);
625                 exec->wait(exec, tMRD);
626         }
627
628         /* update PFB timing registers */
629         exec->timing_set(exec);
630
631         /* DLL (enable + ) reset */
632         if (!(info->mr[1] & mr1_dlloff)) {
633                 if (mr[1] & mr1_dlloff) {
634                         exec->mrs (exec, 1, info->mr[1]);
635                         exec->wait(exec, tMRD);
636                 }
637                 exec->mrs (exec, 0, info->mr[0] | 0x00000100);
638                 exec->wait(exec, tMRD);
639                 exec->mrs (exec, 0, info->mr[0] | 0x00000000);
640                 exec->wait(exec, tMRD);
641                 exec->wait(exec, tDLLK);
642                 if (pfb->ram.type == NV_MEM_TYPE_GDDR3)
643                         exec->precharge(exec);
644         }
645
646         return 0;
647 }