/*XXX: there does appear to be some kind of condition here, simply *modifyingthesebitsinthevbiosfromthedefaultpl0 *entriesshowsnochange.however,thedatadoesappearto *becorrectandmayberequiredforthetransitionback
*/
mask = 0x800f07e0;
data = 0x00030000; if (ram_rd32(fuc, 0x10f978) & 0x00800000)
data |= 0x00040000;
if (1) {
data |= 0x800807e0; switch (next->bios.ramcfg_11_03_c0) { case3: data &= ~0x00000040; break; case2: data &= ~0x00000100; break; case1: data &= ~0x80000000; break; case0: data &= ~0x00000400; break;
}
switch (next->bios.ramcfg_11_03_30) { case3: data &= ~0x00000020; break; case2: data &= ~0x00000080; break; case1: data &= ~0x00080000; break; case0: data &= ~0x00000200; break;
}
}
if (next->bios.ramcfg_11_02_80)
mask |= 0x03000000; if (next->bios.ramcfg_11_02_40)
mask |= 0x00002000; if (next->bios.ramcfg_11_07_10)
mask |= 0x00004000; if (next->bios.ramcfg_11_07_08)
mask |= 0x00000003; else {
mask |= 0x34000000; if (ram_rd32(fuc, 0x10f978) & 0x00800000)
mask |= 0x40000000;
}
ram_mask(fuc, 0x10f824, mask, data);
if (ram->mode != 2) {
u32 data = 0x01000100 * next->bios.ramcfg_11_04;
ram_nuke(fuc, 0x10f694);
ram_mask(fuc, 0x10f694, 0xff00ff00, data);
}
if (ram->mode == 2 && next->bios.ramcfg_11_08_10)
data = 0x00000080; else
data = 0x00000000;
ram_mask(fuc, 0x10f60c, 0x00000080, data);
mask = 0x00070000;
data = 0x00000000; if (!next->bios.ramcfg_11_02_80)
data |= 0x03000000; if (!next->bios.ramcfg_11_02_40)
data |= 0x00002000; if (!next->bios.ramcfg_11_07_10)
data |= 0x00004000; if (!next->bios.ramcfg_11_07_08)
data |= 0x00000003; else
data |= 0x74000000;
ram_mask(fuc, 0x10f824, mask, data);
if (next->bios.ramcfg_11_01_08)
data = 0x00000000; else
data = 0x00001000;
ram_mask(fuc, 0x10f200, 0x00001000, data);
if (next->bios.ramcfg_11_08_01)
data = 0x00100000; else
data = 0x00000000;
ram_mask(fuc, 0x10f82c, 0x00100000, data);
data = 0x00000000; if (next->bios.ramcfg_11_08_08)
data |= 0x00002000; if (next->bios.ramcfg_11_08_04)
data |= 0x00001000; if (next->bios.ramcfg_11_08_02)
data |= 0x00004000;
ram_mask(fuc, 0x10f830, 0x00007000, data);
data = mask = 0x00000000; if (ram->diff.ramcfg_11_08_20) { if (next->bios.ramcfg_11_08_20)
data |= 0x01000000;
mask |= 0x01000000;
}
ram_mask(fuc, 0x10f200, mask, data);
data = mask = 0x00000000; if (ram->diff.ramcfg_11_02_03) {
data |= next->bios.ramcfg_11_02_03 << 8;
mask |= 0x00000300;
} if (ram->diff.ramcfg_11_01_10) { if (next->bios.ramcfg_11_01_10)
data |= 0x70000000;
mask |= 0x70000000;
}
ram_mask(fuc, 0x10f604, mask, data);
data = mask = 0x00000000; if (ram->diff.timing_20_30_07) {
data |= next->bios.timing_20_30_07 << 28;
mask |= 0x70000000;
} if (ram->diff.ramcfg_11_01_01) { if (next->bios.ramcfg_11_01_01)
data |= 0x00000100;
mask |= 0x00000100;
}
ram_mask(fuc, 0x10f614, mask, data);
data = mask = 0x00000000; if (ram->diff.timing_20_30_07) {
data |= next->bios.timing_20_30_07 << 28;
mask |= 0x70000000;
} if (ram->diff.ramcfg_11_01_02) { if (next->bios.ramcfg_11_01_02)
data |= 0x00000100;
mask |= 0x00000100;
}
ram_mask(fuc, 0x10f610, mask, data);
mask = 0x33f00000;
data = 0x00000000; if (!next->bios.ramcfg_11_01_04)
data |= 0x20200000; if (!next->bios.ramcfg_11_07_80)
data |= 0x12800000; /*XXX: see note above about there probably being some condition *forthe10f824stuffthatusesramcfg3...
*/ if (next->bios.ramcfg_11_03_f0) { if (next->bios.rammap_11_08_0c) { if (!next->bios.ramcfg_11_07_80)
mask |= 0x00000020; else
data |= 0x00000020;
mask |= 0x00000004;
}
} else {
mask |= 0x40000020;
data |= 0x00000004;
}
data = mask = 0x00000000; if (ram->diff.ramcfg_11_02_03) {
data |= next->bios.ramcfg_11_02_03;
mask |= 0x00000003;
} if (ram->diff.ramcfg_11_01_10) { if (next->bios.ramcfg_11_01_10)
data |= 0x00000004;
mask |= 0x00000004;
}
data = ram_rd32(fuc, 0x10f978);
data &= ~0x00046144;
data |= 0x0000000b; if (!next->bios.ramcfg_11_07_08) { if (!next->bios.ramcfg_11_07_04)
data |= 0x0000200c; else
data |= 0x00000000;
} else {
data |= 0x00040044;
}
ram_wr32(fuc, 0x10f978, data);
if (ram->mode == 1) {
data = ram_rd32(fuc, 0x10f830) | 0x00000001;
ram_wr32(fuc, 0x10f830, data);
}
if (!next->bios.ramcfg_11_07_08) {
data = 0x88020000; if ( next->bios.ramcfg_11_07_04)
data |= 0x10000000; if (!next->bios.rammap_11_08_10)
data |= 0x00080000;
} else {
data = 0xa40e0000;
}
gk104_ram_train(fuc, 0xbc0f0000, data); if (1) /* XXX: not always? */
ram_nsec(fuc, 1000);
/*XXX: there does appear to be some kind of condition here, simply *modifyingthesebitsinthevbiosfromthedefaultpl0 *entriesshowsnochange.however,thedatadoesappearto *becorrectandmayberequiredforthetransitionback
*/
mask = 0x00010000;
data = 0x00010000;
if (1) {
mask |= 0x800807e0;
data |= 0x800807e0; switch (next->bios.ramcfg_11_03_c0) { case3: data &= ~0x00000040; break; case2: data &= ~0x00000100; break; case1: data &= ~0x80000000; break; case0: data &= ~0x00000400; break;
}
switch (next->bios.ramcfg_11_03_30) { case3: data &= ~0x00000020; break; case2: data &= ~0x00000080; break; case1: data &= ~0x00080000; break; case0: data &= ~0x00000200; break;
}
}
if (next->bios.ramcfg_11_02_80)
mask |= 0x03000000; if (next->bios.ramcfg_11_02_40)
mask |= 0x00002000; if (next->bios.ramcfg_11_07_10)
mask |= 0x00004000; if (next->bios.ramcfg_11_07_08)
mask |= 0x00000003; else
mask |= 0x14000000;
ram_mask(fuc, 0x10f824, mask, data);
mask = 0x00010000;
data = 0x00000000; if (!next->bios.ramcfg_11_02_80)
data |= 0x03000000; if (!next->bios.ramcfg_11_02_40)
data |= 0x00002000; if (!next->bios.ramcfg_11_07_10)
data |= 0x00004000; if (!next->bios.ramcfg_11_07_08)
data |= 0x00000003; else
data |= 0x14000000;
ram_mask(fuc, 0x10f824, mask, data);
ram_nsec(fuc, 1000);
if (next->bios.ramcfg_11_08_01)
data = 0x00100000; else
data = 0x00000000;
ram_mask(fuc, 0x10f82c, 0x00100000, data);
mask = 0x33f00000;
data = 0x00000000; if (!next->bios.ramcfg_11_01_04)
data |= 0x20200000; if (!next->bios.ramcfg_11_07_80)
data |= 0x12800000; /*XXX: see note above about there probably being some condition *forthe10f824stuffthatusesramcfg3...
*/ if (next->bios.ramcfg_11_03_f0) { if (next->bios.rammap_11_08_0c) { if (!next->bios.ramcfg_11_07_80)
mask |= 0x00000020; else
data |= 0x00000020;
mask |= 0x08000004;
}
data |= 0x04000000;
} else {
mask |= 0x44000020;
data |= 0x08000004;
}
data = (next->bios.timing[10] & 0x7f000000) >> 24; if (data < next->bios.timing_20_2c_1fc0)
data = next->bios.timing_20_2c_1fc0;
ram_mask(fuc, 0x10f24c, 0x7f000000, data << 24);
nvkm_error(subdev, "ramcfg data for %dMHz not found\n", mhz); return -EINVAL;
}
staticint
gk104_calc_pll_output(int fN, int M, int N, int P, int clk)
{ return ((clk * N) + (((u16)(fN + 4096) * clk) >> 13)) / (M * P);
}
staticint
gk104_pll_calc_hiclk(int target_khz, int crystal, int *N1, int *fN1, int *M1, int *P1, int *N2, int *M2, int *P2)
{ int best_err = target_khz, p_ref, n_ref; bool upper = false;
*M1 = 1; /* M has to be 1, otherwise it gets unstable */
*M2 = 1; /* can be 1 or 2, sticking with 1 for simplicity */
*P2 = 1;
for (p_ref = 0x7; p_ref >= 0x5; --p_ref) { for (n_ref = 0x25; n_ref <= 0x2b; ++n_ref) { int cur_N, cur_clk, cur_err;
/* XXX: this is *not* what nvidia do. on fermi nvidia generally *select,basedonsomeunknowncondition,oneofthetwopossible *referencefrequencieslistedinthevbiostableformemplland *programrefplltothatfrequency. * *sofar,i'veseenveryweirdvaluesbeingchosenbynvidiaon *keplerboards,noideahow/whythey'rechosen.
*/
refclk = next->freq; if (ram->mode == 2) {
ret = gk104_pll_calc_hiclk(next->freq, subdev->device->crystal,
&ram->N1, &ram->fN1, &ram->M1, &ram->P1,
&ram->N2, &ram->M2, &ram->P2);
fuc->mempll.refclk = ret; if (ret <= 0) {
nvkm_error(subdev, "unable to calc plls\n"); return -EINVAL;
}
nvkm_debug(subdev, "successfully calced PLLs for clock %i kHz" " (refclock: %i kHz)\n", next->freq, ret);
} else { /* calculate refpll coefficients */
ret = gt215_pll_calc(subdev, &fuc->refpll, refclk, &ram->N1,
&ram->fN1, &ram->M1, &ram->P1);
fuc->mempll.refclk = ret; if (ret <= 0) {
nvkm_error(subdev, "unable to calc refpll\n"); return -EINVAL;
}
}
for (i = 0; i < ARRAY_SIZE(fuc->r_mr); i++) { if (ram_have(fuc, mr[i]))
ram->base.mr[i] = ram_rd32(fuc, mr[i]);
}
ram->base.freq = next->freq;
switch (ram->base.type) { case NVKM_RAM_TYPE_DDR3:
ret = nvkm_sddr3_calc(&ram->base); if (ret == 0)
ret = gk104_ram_calc_sddr3(ram, next->freq); break; case NVKM_RAM_TYPE_GDDR5:
ret = nvkm_gddr5_calc(&ram->base, ram->pnuts != 0); if (ret == 0)
ret = gk104_ram_calc_gddr5(ram, next->freq); break; default:
ret = -ENOSYS; break;
}
/* determine type of data for this index */ if (!(data = nvbios_M0205Ep(bios, i, &ver, &hdr, &cnt, &len, &M0205E))) return -ENOENT;
switch (M0205E.type) { case0x00: value = &train->type00; break; case0x01: value = &train->type01; break; case0x04: value = &train->type04; break; case0x06: value = &train->type06; break; case0x07: value = &train->type07; break; case0x08: value = &train->type08; break; case0x09: value = &train->type09; break; default: return0;
}
/* training data index determined by ramcfg strap */ if (!(data = nvbios_M0205Sp(bios, i, ramcfg, &ver, &hdr, &M0205S))) return -EINVAL;
i = M0205S.data;
/* training data format information */ if (!(data = nvbios_M0209Ep(bios, i, &ver, &hdr, &cnt, &len, &M0209E))) return -EINVAL;
/* ... and the raw data */ if (!(data = nvbios_M0209Sp(bios, i, 0, &ver, &hdr, value))) return -EINVAL;
if (M0209E.v02_07 == 2) { /* of course! why wouldn't we have a pointer to another entry *inthesametable,andusethefirstoneasanarrayof *remapindices...
*/ if (!(data = nvbios_M0209Sp(bios, M0209E.v03, 0, &ver, &hdr,
remap))) return -EINVAL;
for (i = 0; i < ARRAY_SIZE(value->data); i++)
value->data[i] = remap->data[value->data[i]];
} else if (M0209E.v02_07 != 1) return -EINVAL;
if (!(cfg = kmalloc(sizeof(*cfg), GFP_KERNEL))) return -ENOMEM;
p = &list_last_entry(&ram->cfg, typeof(*cfg), head)->bios;
n = &cfg->bios;
/* memory config data for a range of target frequencies */
data = nvbios_rammapEp(bios, i, &ver, &hdr, &cnt, &len, &cfg->bios); if (ret = -ENOENT, !data) goto done; if (ret = -ENOSYS, ver != 0x11 || hdr < 0x12) goto done;
/* ... and a portion specific to the attached memory */
data = nvbios_rammapSp(bios, data, ver, hdr, cnt, len, ramcfg,
&ver, &hdr, &cfg->bios); if (ret = -EINVAL, !data) goto done; if (ret = -ENOSYS, ver != 0x11 || hdr < 0x0a) goto done;
/* lookup memory timings, if bios says they're present */ if (cfg->bios.ramcfg_timing != 0xff) {
data = nvbios_timingEp(bios, cfg->bios.ramcfg_timing,
&ver, &hdr, &cnt, &len,
&cfg->bios); if (ret = -EINVAL, !data) goto done; if (ret = -ENOSYS, ver != 0x20 || hdr < 0x33) goto done;
}
list_add_tail(&cfg->head, &ram->cfg); if (ret = 0, i == 0) goto done;
if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) return -ENOMEM;
*pram = &ram->base;
ret = gf100_ram_ctor(func, fb, &ram->base); if (ret) return ret;
INIT_LIST_HEAD(&ram->cfg);
/* calculate a mask of differently configured memory partitions, *because,ofcoursereclockingwasn'tcomplicatedenough *alreadywithouthavingtotreatsomeofthemdifferentlyto *theothers....
*/
ram->parts = nvkm_rd32(device, 0x022438);
ram->pmask = nvkm_rd32(device, 0x022554);
ram->pnuts = 0; for (i = 0, tmp = 0; i < ram->parts; i++) { if (!(ram->pmask & (1 << i))) {
u32 cfg1 = nvkm_rd32(device, 0x110204 + (i * 0x1000)); if (tmp && tmp != cfg1) {
ram->pnuts |= (1 << i); continue;
}
tmp = cfg1;
}
}
/* parse bios data for all rammap table entries up-front, and *buildinformationonwhethercertainfieldsdifferbetween *anyoftheentries. * *thebinarydriverappearstocompletelyignoresomefields *whenallentriescontainthesamevalue.atfirst,itwas *hopedthattheseweremereoptimisationsandthebiosinit *tableshadconfiguredasperthevalueshere,butthereis *evidencenowtosuggestthatthisisn'tthecaseandwedo *needtotreatthisconditionasa"don'ttouch"indicator.
*/ for (i = 0; !ret; i++) {
ret = gk104_ram_ctor_data(ram, ramcfg, i); if (ret && ret != -ENOENT) {
nvkm_error(subdev, "failed to parse ramcfg data\n"); return ret;
}
}
/* parse bios data for both pll's */
ret = nvbios_pll_parse(bios, 0x0c, &ram->fuc.refpll); if (ret) {
nvkm_error(subdev, "mclk refpll data not found\n"); return ret;
}
ret = nvbios_pll_parse(bios, 0x04, &ram->fuc.mempll); if (ret) {
nvkm_error(subdev, "mclk pll data not found\n"); return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.