void time_pgraph_dispatch_clock(unsigned int card) { struct timeval start, end; ptime_t t_start, t_end; u32 reg; if (nva_cards[card]->chipset.card_type == 0x50) reg = 0x4008f8; else if (nva_cards[card]->chipset.card_type == 0xc0) reg = 0x4040f4; else { printf("pgraph_dispatch_clock is only available on nv50+ chipsets\n"); return; } gettimeofday(&start, NULL); t_start = nva_rd32(card, reg); do { gettimeofday(&end, NULL); } while (time_diff_us(start, end) < 1000000); gettimeofday(&end, NULL); t_end = nva_rd32(card, reg); printf("PGRAPH.DISPATCH's clock: 1s = %llu cycles --> frequency = %f MHz\n", (t_end - t_start), (t_end - t_start)/1000000.0); }
void time_pcounter_nv10(unsigned int cnum) { printf ("Perf counter:\n"); nva_wr32(cnum, 0xa73c, 0); nva_wr32(cnum, 0xa404, 0); nva_wr32(cnum, 0xa40c, 0xffff); nva_wr32(cnum, 0xa414, 0xffff); nva_wr32(cnum, 0xa41c, 0); nva_wr32(cnum, 0xa620, 0); nva_wr32(cnum, 0xa624, 0); nva_wr32(cnum, 0xa628, 0); nva_wr32(cnum, 0xa62c, 0); if (nva_cards[cnum]->chipset.card_type >= 0x20) { nva_wr32(cnum, 0xa504, 0); nva_wr32(cnum, 0xa50c, 0xffff); nva_wr32(cnum, 0xa514, 0xffff); nva_wr32(cnum, 0xa51c, 0); nva_wr32(cnum, 0xa720, 0); nva_wr32(cnum, 0xa724, 0); nva_wr32(cnum, 0xa728, 0); nva_wr32(cnum, 0xa72c, 0); nva_wr32(cnum, 0xa504, 0xffff); } nva_wr32(cnum, 0xa404, 0xffff); sleep(1); printf ("Set 0: %d Hz\n", nva_rd32(cnum, 0xa608)); if (nva_cards[cnum]->chipset.card_type >= 0x20) { printf ("Set 1: %u Hz\n", nva_rd32(cnum, 0xa708)); } }
void time_pwm_nv50(unsigned int cnum) { int i; for (i = 0; i < 2; i++) { uint32_t a = 0xe114 + i * 8; uint32_t b = a + 4; uint32_t save0 = nva_rd32(cnum, a); uint32_t save1 = nva_rd32(cnum, b); struct timeval start, end; nva_wr32(cnum, a, 0x200000); nva_wr32(cnum, b, 0x80080000); while (nva_rd32(cnum, b) & 0x80000000); nva_wr32(cnum, b, 0x80080000); while (nva_rd32(cnum, b) & 0x80000000); gettimeofday(&start, NULL); nva_wr32(cnum, b, 0x80080000); while (nva_rd32(cnum, b) & 0x80000000); gettimeofday(&end, NULL); uint64_t td = (time_diff_us(start, end)); printf("PWM %d: %dHz\n", i, (int)(1000000ll * 0x200000 / td)); nva_wr32(cnum, a, save0); nva_wr32(cnum, b, 0x80000000 | save1); } }
static int threshold_check_state(struct hwtest_ctx *ctx, const struct therm_threshold *thrs) { int i, dir, temp, exp_state; threshold_reset(ctx); nva_mask(ctx->cnum, 0x20010, 0x80000000, 0x80000000); i = 1; dir = 1; while (i > 0) { /* set the threshold */ threshold_set(ctx, thrs, i); /* calculate the expected state */ do { temp = nva_rd32(ctx->cnum, 0x20014) & 0x3fff; if (thrs->dir_inverted) exp_state = (temp < i); else exp_state = (temp > i); } while (temp != (nva_rd32(ctx->cnum, 0x20014) & 0x3fff)); /* check the state */ TEST_READ_MASK(thrs->dir_addr, exp_state << thrs->dir_status_bit, 1 << thrs->dir_status_bit, "invalid state at temperature %i: dir (%i), threshold (%i)", temp, dir, i); if (i == 0x3fff) dir = -1; i += dir; } return HWTEST_RES_PASS; }
/* vbios should at least be NV_PROM_SIZE bytes long */ int vbios_upload_pramin(int cnum, uint8_t *vbios, int length) { uint64_t old_bar0_pramin = 0; uint32_t ret = EUNK; int i = 0; if (nva_cards[cnum]->chipset.chipset < 0x04) { return ECARD; } /* Update the checksum */ chksum(vbios, length); fprintf(stderr, "Attempt to upload the vbios to card %i (nv%02x) using PRAMIN\n", cnum, nva_cards[cnum]->chipset.chipset); if (nva_cards[cnum]->chipset.card_type >= 0x50) { uint64_t vbios_vram = (uint64_t)(nva_rd32(cnum, 0x619f04) & ~0xff) << 8; if (!vbios_vram) vbios_vram =((uint64_t)nva_rd32(cnum, 0x1700) << 16) + 0xf0000; old_bar0_pramin = nva_rd32(cnum, 0x1700); nva_wr32(cnum, 0x1700, vbios_vram >> 16); }
uint32_t xt_rd32(int cnum, uint32_t addr) { nva_wr32(cnum, 0x700004, addr); nva_wr32(cnum, 0x70000, 1); while (nva_rd32(cnum, 0x70000)); nva_wr32(cnum, 0x700000, 1); while (nva_rd32(cnum, 0x700000)); return nva_rd32(cnum, 0x700004); }
static void nv01_pgraph_gen_state(struct hwtest_ctx *ctx, struct nv01_pgraph_state *state) { if (sizeof *state != sizeof nv01_pgraph_state_regs) abort(); int i; uint32_t *rawstate = (uint32_t *)state; for (i = 0; i < ARRAY_SIZE(nv01_pgraph_state_regs); i++) rawstate[i] = jrand48(ctx->rand48); state->debug[0] &= 0x11111110; state->debug[1] &= 0x31111101; state->debug[2] &= 0x11111111; state->intr = 0; state->invalid = 0; state->intr_en &= 0x11111011; state->invalid_en &= 0x00011111; state->ctx_switch &= 0x807fffff; state->ctx_control &= 0x11010103; /* no change for VTX ram */ for (i = 0; i < 14; i++) state->vtx_beta[i] &= 0x01ffffff; for (i = 0; i < 2; i++) { state->iclip[i] &= 0x3ffff; state->uclip_min[i] &= 0x3ffff; state->uclip_max[i] &= 0x3ffff; state->pattern_rgb[i] &= 0x3fffffff; state->pattern_a[i] &= 0xff; state->pattern_bitmap[i] &= 0xffffffff; state->bitmap_color[i] &= 0x7fffffff; } state->pattern_shape &= 3; state->rop &= 0xff; state->plane &= 0x7fffffff; state->chroma &= 0x7fffffff; state->beta &= 0x7f800000; state->canvas_config &= 0x01111011; state->xy_misc_0 &= 0xf1ff11ff; state->xy_misc_1 &= 0x03177331; state->xy_misc_2[0] &= 0x30ffffff; state->xy_misc_2[1] &= 0x30ffffff; state->valid &= 0x111ff1ff; /* source color: no change */ state->subdivide &= 0xffff00ff; state->edgefill &= 0xffff0113; state->dma &= 0xffff; state->notify &= 0x11ffff; state->canvas_min &= 0xffffffff; state->canvas_max &= 0x0fff0fff; state->cliprect_min[0] &= 0x0fff0fff; state->cliprect_min[1] &= 0x0fff0fff; state->cliprect_max[0] &= 0x0fff0fff; state->cliprect_max[1] &= 0x0fff0fff; state->cliprect_ctrl &= 0x113; state->access &= 0x0001f000; state->access |= 0x0f000111; state->status = 0; state->pfb_config &= 0x1370; state->pfb_config |= nva_rd32(ctx->cnum, 0x600200) & ~0x1371; state->pfb_boot = nva_rd32(ctx->cnum, 0x600000); }
uint32_t xt_rsr(int cnum, uint32_t sr, uint32_t *status) { nva_wr32(cnum, 0x700004, sr); nva_wr32(cnum, 0x70000, 1); while (nva_rd32(cnum, 0x70000)); nva_wr32(cnum, 0x700000, 3); while (nva_rd32(cnum, 0x700000)); *status = nva_rd32(cnum, 0x70000c); return nva_rd32(cnum, 0x700004); }
void nv40_stop_monitoring(int cnum, int set, uint8_t *signals, uint32_t *real_signals, uint32_t *cycles) { uint32_t cycles_cnt, s[4]; uint8_t w_s[4]; int i; /* readout */ nva_mask(cnum, 0x400084, 0x0, 0x20); w_s[0] = nva_rd32(cnum, 0xa400 + set * 4); w_s[1] = nva_rd32(cnum, 0xa440 + set * 4); w_s[2] = nva_rd32(cnum, 0xa480 + set * 4); w_s[3] = nva_rd32(cnum, 0xa4c0 + set * 4); cycles_cnt = nva_rd32(cnum, 0xa600 + set * 4); s[0] = nva_rd32(cnum, 0xa700 + set * 4); s[1] = nva_rd32(cnum, 0xa6c0 + set * 4); s[2] = nva_rd32(cnum, 0xa680 + set * 4); s[3] = nva_rd32(cnum, 0xa740 + set * 4); for (i = 0; i < 4; i++) { if (signals) SIGNAL_VALUE(signals, set, w_s[i]) = s[i] * 100 / cycles_cnt; if (real_signals) SIGNAL_VALUE(real_signals, set, w_s[i]) = s[i]; if (cycles) SIGNAL_VALUE(cycles, set, w_s[i]) = cycles_cnt; } }
u64 crystal_type(unsigned int card) { unsigned int crystal, chipset; chipset = nva_cards[card]->chipset.chipset; crystal = (nva_rd32(card, 0x101000) & 0x40) >> 6; if ((chipset >= 0x17 && chipset < 0x20) || chipset > 0x25) { crystal += (nva_rd32(card, 0x101000) & 0x400000) >> 21; }
int main(int argc, char **argv) { if (nva_init()) { fprintf (stderr, "PCI init failure!\n"); return 1; } int c; int cnum =0; while ((c = getopt (argc, argv, "c:")) != -1) switch (c) { case 'c': sscanf(optarg, "%d", &cnum); break; } if (cnum >= nva_cardsnum) { if (nva_cardsnum) fprintf (stderr, "No such card.\n"); else fprintf (stderr, "No cards found.\n"); return 1; } uint32_t m, d, ctrl; if (optind + 3 > argc) { fprintf (stderr, "%s: <channel> <method> <data>\n", argv[0]); return 1; } sscanf (argv[optind + 0], "%d", &c); sscanf (argv[optind + 1], "%x", &m); sscanf (argv[optind + 2], "%x", &d); if (nva_cards[cnum].chipset >= 0xd0) { ctrl = nva_rd32(cnum, 0x610700 + (c * 8)); nva_wr32(cnum, 0x610700 + (c * 8), ctrl | 1); nva_wr32(cnum, 0x610704 + (c * 8), d); nva_wr32(cnum, 0x610700 + (c * 8), 0x80000001 | m); while (nva_rd32(cnum, 0x610700 + (c * 8)) & 0x80000000); nva_wr32(cnum, 0x610700 + (c * 8), ctrl); } else if (nva_cards[cnum].chipset == 0x50 || nva_cards[cnum].chipset >= 0x84) { ctrl = nva_rd32(cnum, 0x610300 + (c * 8)); nva_wr32(cnum, 0x610300 + (c * 8), ctrl | 1); nva_wr32(cnum, 0x610304 + (c * 8), d); nva_wr32(cnum, 0x610300 + (c * 8), 0x80000001 | m); while (nva_rd32(cnum, 0x610300 + (c * 8)) & 0x80000000); nva_wr32(cnum, 0x610300 + (c * 8), ctrl); } else { fprintf (stderr, "unsupported chipset\n"); return 1; } return 0; }
void *watchfun(void *x) { uint32_t val = nva_rd32(cnum, a); queue[put] = val; put = (put + 1) % SZ; while (1) { uint32_t nval = nva_rd32(cnum, a); if (nval != val) { queue[put] = nval; put = (put + 1) % SZ; } val = nval; } }
void find_ptimer_b12(int cnum) { uint8_t signals_ref_timer[0x100 * 8]; uint8_t signals_tmp[0x100 * 8]; struct signals_comparaison diffs; int i; uint32_t r_9210, r_9400; printf("<PTIMER_B12>\n"); r_9210 = nva_rd32(cnum, 0x9210); r_9400 = nva_rd32(cnum, 0x9400); /* stop the time */ nva_wr32(cnum, 0x9210, 0); nva_wr32(cnum, 0x9400, 0); poll_signals(cnum, signals_ref_timer); nva_wr32(cnum, 0x9400, 0x20000); poll_signals(cnum, signals_tmp); /* restore ptimer */ nva_wr32(cnum, 0x9400, r_9400); nva_wr32(cnum, 0x9210, r_9210); diffs = signals_compare(signals_ref_timer, signals_tmp); if (diffs.diff_count >= 1) { for (i = 0; i < diffs.diff_count; i++) { uint8_t set, signal; set = diffs.differences[i].set; signal = diffs.differences[i].signal; if (diffs.differences[i].set == 0) { if (diffs.differences[i].change == ZERO_TO_ONE) printf("PTIMER_B12: Set %u, signal 0x%.2x\n", set, signal); } else { printf("Unexpected difference: "); print_difference(diffs.differences[i]); } } } else printf("Not found.\n"); signals_comparaison_free(diffs); printf("</PTIMER_B12>\n\n"); }
uint32_t vram_rd32(int card, uint64_t addr) { if (nva_cards[card].card_type < 3) { return nva_rd32(card, 0x1000000 + addr); } else if (nva_cards[card].card_type < 0x30) { return nva_grd32(nva_cards[card].bar1, addr); } else if (nva_cards[card].card_type < 0x50) { nva_wr32(card, 0x1570, addr); return nva_rd32(card, 0x1574); } else { uint32_t old = nva_rd32(card, 0x1700); nva_wr32(card, 0x1700, addr >> 16); uint32_t res = nva_rd32(card, 0x700000 | (addr & 0xffff)); nva_wr32(card, 0x1700, old); return res; } }
static int test_scan_context(struct hwtest_ctx *ctx) { nva_wr32(ctx->cnum, 0x4006a4, 0x0f000111); TEST_BITSCAN(0x400600, 0x3fffffff, 0); TEST_BITSCAN(0x400604, 0xff, 0); TEST_BITSCAN(0x400608, 0x3fffffff, 0); TEST_BITSCAN(0x40060c, 0xff, 0); TEST_BITSCAN(0x400610, 0xffffffff, 0); TEST_BITSCAN(0x400614, 0xffffffff, 0); TEST_BITSCAN(0x400618, 3, 0); TEST_BITSCAN(0x40061c, 0x7fffffff, 0); TEST_BITSCAN(0x400620, 0x7fffffff, 0); TEST_BITSCAN(0x400624, 0xff, 0); TEST_BITSCAN(0x400628, 0x7fffffff, 0); TEST_BITSCAN(0x40062c, 0x7fffffff, 0); TEST_BITSCAN(0x400680, 0x0000ffff, 0); TEST_BITSCAN(0x400684, 0x0011ffff, 0); int i; for (i = 0; i < 1000; i++) { uint32_t orig = jrand48(ctx->rand48); nva_wr32(ctx->cnum, 0x400630, orig); uint32_t exp = orig & 0x7f800000; if (orig & 0x80000000) exp = 0; uint32_t real = nva_rd32(ctx->cnum, 0x400630); if (real != exp) { printf("BETA scan mismatch: orig %08x expected %08x real %08x\n", orig, exp, real); return HWTEST_RES_FAIL; } } return HWTEST_RES_PASS; }
static int threshold_gen_intr_dir(struct hwtest_ctx *ctx, struct therm_threshold *thrs, int dir) { int temp, lower_thrs, higher_thrs, tmp; temp = nva_rd32(ctx->cnum, 0x20014) & 0xffff; lower_thrs = temp - 0x100; higher_thrs = temp + 0x100; if (lower_thrs < 0) lower_thrs = 0; if (dir > 0) tmp = lower_thrs; else tmp = higher_thrs; threshold_set(ctx, thrs, tmp); /* enable the IRQs */ nva_wr32(ctx->cnum, 0x1140, 0x70000); /* ACK any IRQ */ nva_wr32(ctx->cnum, 0x1100, 0xffffffff); /* ack pbus' IRQs */ /* Generate an IRQ */ if (dir > 0) tmp = higher_thrs; else tmp = lower_thrs; threshold_set(ctx, thrs, tmp); /* necessary */ usleep(1); return HWTEST_RES_PASS; }
static int test_temperature_enable_state(struct hwtest_ctx *ctx) { uint32_t r010 = nva_mask(ctx->cnum, 0x20010, 0x40000000, 0x40000000); uint32_t temp_disabled, temp_enabled; temp_disabled = nva_rd32(ctx->cnum, 0x20014) & 0x3fff; nva_wr32(ctx->cnum, 0x20010, 0); usleep(20000); temp_enabled = nva_rd32(ctx->cnum, 0x20014) & 0x3fff; nva_wr32(ctx->cnum, 0x20010, r010); if (temp_disabled == 0 && temp_enabled) return HWTEST_RES_PASS; else return HWTEST_RES_FAIL; }
uint32_t host_xt_rd32(int cnum, uint32_t xt_addr) { uint32_t host_addr = pbsp_get_host_addr(xt_addr); uint32_t index = pbsp_get_host_index(xt_addr); nva_wr32(cnum, HOST_XTENSA_INDEX, index); return nva_rd32(cnum, host_addr); }
void vram_wr32(int card, uint64_t addr, uint32_t val) { if (nva_cards[card].card_type < 3) { nva_wr32(card, 0x1000000 + addr, val); } else if (nva_cards[card].card_type < 0x30) { nva_gwr32(nva_cards[card].bar1, addr, val); } else if (nva_cards[card].card_type < 0x50) { nva_wr32(card, 0x1570, addr); nva_wr32(card, 0x1574, val); } else { uint32_t old = nva_rd32(card, 0x1700); nva_wr32(card, 0x1700, addr >> 16); nva_wr32(card, 0x700000 | (addr & 0xffff), val); nva_wr32(card, 0x1700, old); nva_wr32(card, 0x70000, 1); while (nva_rd32(card, 0x70000) & 2); } }
static uint64_t get_time(unsigned int card) { uint64_t low; /* From kmmio dumps on nv28 this looks like how the blob does this. * It reads the high dword twice, before and after. * The only explanation seems to be that the 64-bit timer counter * advances between high and low dword reads and may corrupt the * result. Not confirmed. */ uint64_t high2 = nva_rd32(card, 0x9410); uint64_t high1; do { high1 = high2; low = nva_rd32(card, 0x9400); high2 = nva_rd32(card, 0x9410); } while (high1 != high2); return ((((uint64_t)high2) << 32) | (uint64_t)low); }
void time_pcounter_nv40(unsigned int cnum) { printf ("Perf counters:\n"); int i; uint32_t debug1 = nva_rd32(cnum, 0x400084); for (i = 0; i < 8; i++) { nva_wr32(cnum, 0xa7c0 + i * 4, 0x1); nva_wr32(cnum, 0xa460 + i * 4, 0); nva_wr32(cnum, 0xa4a0 + i * 4, 0); nva_wr32(cnum, 0xa4e0 + i * 4, 0); nva_wr32(cnum, 0xa500 + i * 4, 0); nva_wr32(cnum, 0xa520 + i * 4, 0); nva_wr32(cnum, 0xa420 + i * 4, 0xffff); nva_wr32(cnum, 0x400084, debug1 | 0x20); sleep(1); nva_wr32(cnum, 0x400084, debug1 | 0x20); printf ("Set %d: %u Hz\n", i, nva_rd32(cnum, 0xa600 + i * 4)); } }
void time_pcounter_nvc0(unsigned int cnum) { printf ("Perf counters:\n"); int parts = nva_rd32(cnum, 0x121c74); int gpcs = nva_rd32(cnum, 0x121c78); int i, u; for (i = 0; i < 8; i++) { nva_wr32(cnum, 0x1b009c + i * 0x200, 0x40002); nva_wr32(cnum, 0x1b0044 + i * 0x200, 0xffff); nva_wr32(cnum, 0x1b00a8 + i * 0x200, 0); } sleep(1); for (i = 0; i < 8; i++) printf ("HUB set %d: %d Hz\n", i, nva_rd32(cnum, 0x1b00a8 + i * 0x200)); for (u = 0; u < parts; u++) { for (i = 0; i < 2; i++) { nva_wr32(cnum, 0x1a009c + i * 0x200 + u * 0x1000, 0x40002); nva_wr32(cnum, 0x1a0044 + i * 0x200 + u * 0x1000, 0xffff); nva_wr32(cnum, 0x1a00a8 + i * 0x200 + u * 0x1000, 0); } sleep(1); for (i = 0; i < 2; i++) printf ("ROPC[%d] set %d: %d Hz\n", u, i, nva_rd32(cnum, 0x1a00a8 + i * 0x200 + u * 0x1000)); } for (u = 0; u < gpcs; u++) { for (i = 0; i < 1; i++) { nva_wr32(cnum, 0x18009c + i * 0x200 + u * 0x1000, 0x40002); nva_wr32(cnum, 0x180044 + i * 0x200 + u * 0x1000, 0xffff); nva_wr32(cnum, 0x1800a8 + i * 0x200 + u * 0x1000, 0); } sleep(1); for (i = 0; i < 1; i++) printf ("GPC[%d] set %d: %d Hz\n", u, i, nva_rd32(cnum, 0x1800a8 + i * 0x200 + u * 0x1000)); } }
static int test_scan_access(struct hwtest_ctx *ctx) { uint32_t val = nva_rd32(ctx->cnum, 0x4006a4); int i; for (i = 0; i < 1000; i++) { uint32_t nv = jrand48(ctx->rand48); uint32_t next = val; nva_wr32(ctx->cnum, 0x4006a4, nv); if (nv & 1 << 24) insrt(next, 0, 1, extr(nv, 0, 1)); if (nv & 1 << 25) insrt(next, 4, 1, extr(nv, 4, 1)); if (nv & 1 << 26) insrt(next, 8, 1, extr(nv, 8, 1)); if (nv & 1 << 27) insrt(next, 12, 5, extr(nv, 12, 5)); uint32_t real = nva_rd32(ctx->cnum, 0x4006a4); if (real != next) { printf("ACCESS mismatch: prev %08x write %08x expected %08x real %08x\n", val, nv, next, real); return HWTEST_RES_FAIL; } val = next; } return HWTEST_RES_PASS; }
/* vbios should at least be NV_PROM_SIZE bytes long */ int vbios_extract_pramin(int cnum, uint8_t *vbios, int *length) { uint32_t old_bar0_pramin = 0; uint32_t ret = EUNK; int i; if (nva_cards[cnum].chipset < 0x04) { fprintf(stderr, "Card %i (nv%02x) does not support PRAMIN!\n", cnum, nva_cards[cnum].chipset); return ECARD; } fprintf(stderr, "Attempt to extract the vbios from card %i (nv%02x) using PRAMIN\n", cnum, nva_cards[cnum].chipset); if (nva_cards[cnum].card_type >= 0x50) { uint64_t vbios_vram = (uint64_t)(nva_rd32(cnum, 0x619f04) & ~0xff) << 8; if (!vbios_vram) vbios_vram = ((uint64_t)nva_rd32(cnum, 0x1700) << 16) + 0xf0000; old_bar0_pramin = nva_rd32(cnum, 0x1700); nva_wr32(cnum, 0x1700, vbios_vram >> 16); }
void time_pcounter_nv84(unsigned int cnum) { printf ("Perf counters:\n"); int i; for (i = 0; i < 8; i++) { nva_wr32(cnum, 0xa7c0 + i * 4, 1); nva_wr32(cnum, 0xa420 + i * 4, 0xffff); } sleep(1); for (i = 0; i < 8; i++) nva_wr32(cnum, 0xa420 + i * 4, 0xffff); for (i = 0; i < 8; i++) printf ("Set %d: %u Hz\n", i, nva_rd32(cnum, 0xa600 + i * 4)); }
static int test_scan_canvas(struct hwtest_ctx *ctx) { nva_wr32(ctx->cnum, 0x4006a4, 0x0f000111); TEST_BITSCAN(0x400634, 0x01111011, 0); nva_wr32(ctx->cnum, 0x400688, 0x7fff7fff); if(nva_rd32(ctx->cnum, 0x400688) != 0x7fff7fff) { return HWTEST_RES_FAIL; } TEST_BITSCAN(0x400688, 0xffffffff, 0); TEST_BITSCAN(0x40068c, 0x0fff0fff, 0); TEST_BITSCAN(0x400690, 0x0fff0fff, 0); TEST_BITSCAN(0x400694, 0x0fff0fff, 0); TEST_BITSCAN(0x400698, 0x0fff0fff, 0); TEST_BITSCAN(0x40069c, 0x0fff0fff, 0); TEST_BITSCAN(0x4006a0, 0x113, 0); return HWTEST_RES_PASS; }
void strwait() { int ctr = 0; while (nva_rd32(cnum, 0x400404) & 0x20000 || nva_rd32(cnum, 0x400400) || nva_rd32(cnum, 0x400700) & 0x100 || nva_rd32(cnum, 0x40082c & 0x800)) { ctr++; if (ctr > 0x1000000) { printf("Aiiii, xfer is hung. bailing.\n"); exit(1); } } while (nva_rd32(cnum, 0x400404) & 0x20000 || nva_rd32(cnum, 0x400400) || nva_rd32(cnum, 0x400700) & 0x100 || nva_rd32(cnum, 0x40082c & 0x800)); }
void poll_signals(int cnum, uint8_t *signals) { int i, j, b; for (i = 0; i < SIGNALS_LENGTH * 8; i++) signals[i] = 0; for (i = 0; i < 100; i++) { for (j = 0; j < SIGNALS_LENGTH; j+=4) { uint32_t value = nva_rd32(cnum, 0xa800 + j); for (b = 0; b < 32; b++) if (value & (1 << b)) signals[j * 8 + b]++; } } }
static int nv50_threshold_filter(struct hwtest_ctx *ctx, const struct therm_threshold *thrs) { uint8_t div, cycles; uint64_t before; uint64_t after; /* get the data */ for (div = 0; div < 4; div++) { for (cycles = 1; cycles < 3; cycles++) { threshold_reset(ctx); nva_mask(ctx->cnum, 0x20010, 0x80000000, 0x80000000); threshold_filter_set(ctx, thrs, 0, 0); threshold_set(ctx, thrs, 0x3fff); nva_wr32(ctx->cnum, 0x1100, 0x70000); threshold_set_intr_dir(ctx, thrs, 3); threshold_filter_set(ctx, thrs, div, (cycles * 0x7f)); before = get_time(ctx->cnum); threshold_set(ctx, thrs, 10); while ((nva_rd32(ctx->cnum, 0x1100) & 0x70000) == 0); after = get_time(ctx->cnum); uint64_t time = after - before; double clock_hz = (1000000.0 / (16.0 * pow(16, div))); double expected_time = (1.0 / clock_hz) * cycles * 0x7f * 1e9; double prediction_error = abs(time - expected_time) * 100.0 / expected_time; if (prediction_error > 5.0) { printf("div %x => %f, cycles 0x%x: delay %"PRIu64"; expected delay %.0f (prediction_error = %f%%), clock_hz = %f\n", div, 32 * pow(16, div), cycles * 0x7f, time, expected_time, prediction_error, clock_hz); return HWTEST_RES_FAIL; } } } return HWTEST_RES_PASS; }
/* vbios should at least be NV_PROM_SIZE bytes long */ int vbios_extract_prom(int cnum, uint8_t *vbios, int *length) { uint32_t pci_cfg_50 = 0; uint32_t ret = EUNK; int i; fprintf(stderr, "Attempt to extract the vbios from card %i (nv%02x) using PROM\n", cnum, nva_cards[cnum].chipset); int32_t prom_offset; int32_t prom_size; int32_t pbus_offset = 0; if (nva_cards[cnum].chipset < 0x03) { prom_offset = 0x610000; prom_size = NV01_PROM_SIZE; } else if (nva_cards[cnum].chipset < 0x04) { prom_offset = 0x110000; prom_size = NV03_PROM_SIZE; } else { if (nva_cards[cnum].chipset < 0x40) pbus_offset = 0x1800; else pbus_offset = 0x88000; prom_offset = 0x300000; prom_size = NV_PROM_SIZE; pci_cfg_50 = nva_rd32(cnum, pbus_offset + 0x50); nva_wr32(cnum, pbus_offset + 0x50, 0); } /* on some 6600GT/6800LE prom reads are messed up. nvclock alleges a * a good read may be obtained by waiting or re-reading (cargocult: 5x) * each byte. we'll hope pramin has something usable instead */ for (i = 0; i < prom_size; i++) vbios[i] = nva_rd8(cnum, prom_offset + i); ret = nv_ckbios(vbios, length); if (nva_cards[cnum].chipset >= 0x04) { nva_wr32(cnum, pbus_offset + 0x50, pci_cfg_50); } return ret; }