0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include "priv.h"
0026 #include "ram.h"
0027
0028 struct ramxlat {
0029 int id;
0030 u8 enc;
0031 };
0032
0033 static inline int
0034 ramxlat(const struct ramxlat *xlat, int id)
0035 {
0036 while (xlat->id >= 0) {
0037 if (xlat->id == id)
0038 return xlat->enc;
0039 xlat++;
0040 }
0041 return -EINVAL;
0042 }
0043
0044 static const struct ramxlat
0045 ramddr2_cl[] = {
0046 { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 },
0047
0048 { 7, 7 },
0049 { -1 }
0050 };
0051
0052 static const struct ramxlat
0053 ramddr2_wr[] = {
0054 { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 4 }, { 6, 5 },
0055
0056 { 7, 6 },
0057 { -1 }
0058 };
0059
0060 int
0061 nvkm_sddr2_calc(struct nvkm_ram *ram)
0062 {
0063 int CL, WR, DLL = 0, ODT = 0;
0064
0065 switch (ram->next->bios.timing_ver) {
0066 case 0x10:
0067 CL = ram->next->bios.timing_10_CL;
0068 WR = ram->next->bios.timing_10_WR;
0069 DLL = !ram->next->bios.ramcfg_DLLoff;
0070 ODT = ram->next->bios.timing_10_ODT & 3;
0071 break;
0072 case 0x20:
0073 CL = (ram->next->bios.timing[1] & 0x0000001f);
0074 WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
0075 break;
0076 default:
0077 return -ENOSYS;
0078 }
0079
0080 if (ram->next->bios.timing_ver == 0x20 ||
0081 ram->next->bios.ramcfg_timing == 0xff) {
0082 ODT = (ram->mr[1] & 0x004) >> 2 |
0083 (ram->mr[1] & 0x040) >> 5;
0084 }
0085
0086 CL = ramxlat(ramddr2_cl, CL);
0087 WR = ramxlat(ramddr2_wr, WR);
0088 if (CL < 0 || WR < 0)
0089 return -EINVAL;
0090
0091 ram->mr[0] &= ~0xf70;
0092 ram->mr[0] |= (WR & 0x07) << 9;
0093 ram->mr[0] |= (CL & 0x07) << 4;
0094
0095 ram->mr[1] &= ~0x045;
0096 ram->mr[1] |= (ODT & 0x1) << 2;
0097 ram->mr[1] |= (ODT & 0x2) << 5;
0098 ram->mr[1] |= !DLL;
0099 return 0;
0100 }