|
@@ -146,6 +146,38 @@ nv50_ram_timing_calc(struct nv50_ram *ram, u32 *timing)
|
|
|
nvkm_debug(subdev, " 240: %08x\n", timing[8]);
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
+static int
|
|
|
+nv50_ram_timing_read(struct nv50_ram *ram, u32 *timing)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+ struct nvbios_ramcfg *cfg = &ram->base.target.bios;
|
|
|
+ struct nvkm_subdev *subdev = &ram->base.fb->subdev;
|
|
|
+ struct nvkm_device *device = subdev->device;
|
|
|
+
|
|
|
+ for (i = 0; i <= 8; i++)
|
|
|
+ timing[i] = nvkm_rd32(device, 0x100220 + (i * 4));
|
|
|
+
|
|
|
+ /* Derive the bare minimum for the MR calculation to succeed */
|
|
|
+ cfg->timing_ver = 0x10;
|
|
|
+ T(CL) = (timing[3] & 0xff) + 1;
|
|
|
+
|
|
|
+ switch (ram->base.type) {
|
|
|
+ case NVKM_RAM_TYPE_DDR2:
|
|
|
+ T(CWL) = T(CL) - 1;
|
|
|
+ break;
|
|
|
+ case NVKM_RAM_TYPE_GDDR3:
|
|
|
+ T(CWL) = ((timing[2] & 0xff000000) >> 24) + 1;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -ENOSYS;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ T(WR) = ((timing[1] >> 24) & 0xff) - 1 - T(CWL);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
#undef T
|
|
|
|
|
|
static void
|
|
@@ -242,10 +274,11 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
|
|
|
strap, data, ver, hdr);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
+ nv50_ram_timing_calc(ram, timing);
|
|
|
+ } else {
|
|
|
+ nv50_ram_timing_read(ram, timing);
|
|
|
}
|
|
|
|
|
|
- nv50_ram_timing_calc(ram, timing);
|
|
|
-
|
|
|
ret = ram_init(hwsq, subdev);
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -264,8 +297,10 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if (ret)
|
|
|
+ if (ret) {
|
|
|
+ nvkm_error(subdev, "Could not calculate MR\n");
|
|
|
return ret;
|
|
|
+ }
|
|
|
|
|
|
/* Always disable this bit during reclock */
|
|
|
ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000);
|