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 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; }
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; }
static t_threshold *threshold_new(t_floatarg hithresh, t_floatarg hideadtime, t_floatarg lothresh, t_floatarg lodeadtime) { t_threshold *x = (t_threshold *) pd_new(threshold_class); x->x_state = 0; /* low state */ x->x_deadwait = 0; /* no dead time */ x->x_clock = clock_new(x, (t_method)threshold_tick); x->x_outlet1 = outlet_new(&x->x_obj, gensym("bang")); x->x_outlet2 = outlet_new(&x->x_obj, gensym("bang")); threshold_set(x, hithresh, hideadtime, lothresh, lodeadtime); return (x); }