diff --git a/cgminer.c b/cgminer.c index 804fe0cf36..0775e9a46d 100644 --- a/cgminer.c +++ b/cgminer.c @@ -279,6 +279,10 @@ static char *opt_set_avalon8_voltage_level; static char *opt_set_avalon8_voltage_level_offset; static char *opt_set_avalon8_freq; static char *opt_set_avalon8_asic_otp; +static char *opt_set_avalon8_freq_adjust_step; +static char *opt_set_avalon8_voltage_level_adjust_step; +static char *opt_set_avalon8_temp_add_freq_voltage; +static char *opt_set_avalon8_temp_sub_freq_voltage; #endif #ifdef USE_AVALON_MINER static char *opt_set_avalonm_voltage; @@ -1588,6 +1592,18 @@ static struct opt_table opt_config_table[] = { OPT_WITH_CBARG("--avalon8-cinfo-asic", set_avalon8_asic_otp, NULL, &opt_set_avalon8_asic_otp, "Set Avalon8 cinfo asic index, range:[0, 25], step: 1"), + OPT_WITH_CBARG("--avalon8-freq-adjust-step", + set_avalon8_freq_adjust_step, NULL, &opt_set_avalon8_freq_adjust_step, + "Set Avalon8 default adjust step frequency, frequency level:[1, 2, 3, 4]"), + OPT_WITH_CBARG("--avalon8-voltage-level-adjust-step", + set_avalon8_voltage_level_adjust_step, NULL, &opt_set_avalon8_voltage_level_adjust_step, + "Set Avalon8 adjust step level of core voltage, range:[0, 15], step: 1"), + OPT_WITH_ARG("--avalon8-temp-sub-freq-voltage", + set_avalon8_temp_sub_freq_voltage, NULL, &opt_set_avalon8_temp_sub_freq_voltage, + "Set Avalon8 target temperature for subtracting freq and voltage, range:[60, 100], step: 1"), + OPT_WITH_ARG("--avalon8-temp-add-freq-voltage", + set_avalon8_temp_add_freq_voltage, NULL, &opt_set_avalon8_temp_add_freq_voltage, + "Set Avalon8 target temperature for adding freq and voltage, range:[60, 100], step: 1"), #endif #ifdef USE_AVALON_MINER OPT_WITH_CBARG("--avalonm-voltage", diff --git a/driver-avalon8.c b/driver-avalon8.c index 3a8218313e..991c038328 100644 --- a/driver-avalon8.c +++ b/driver-avalon8.c @@ -27,6 +27,11 @@ int opt_avalon8_fan_max = AVA8_DEFAULT_FAN_MAX; int opt_avalon8_voltage_level = AVA8_INVALID_VOLTAGE_LEVEL; int opt_avalon8_voltage_level_offset = AVA8_DEFAULT_VOLTAGE_LEVEL_OFFSET; +int opt_avalon8_freq_adjust_step = AVA8_INVALID_FREQ_ADJUST_STEP; +int opt_avalon8_voltage_level_adjust_step = AVA8_DEFAULT_VOLT_ADJUST_STEP; +int opt_avalon8_temp_add_freq_voltage = AVA8_INVALID_TEMP_ADD_FREQ_VOLTAGE; +int opt_avalon8_temp_sub_freq_voltage = AVA8_INVALID_TEMP_SUB_FREQ_VOLTAGE; + int opt_avalon8_asic_otp = AVA8_INVALID_ASIC_OTP; static uint8_t opt_avalon8_cycle_hit_flag; @@ -224,6 +229,18 @@ static double decode_pvt_temp(uint16_t pvt_code) return g + h * (pvt_code / cal5 - 0.5) + j * fclkm; } +static uint16_t encode_pvt_temp(double temp) +{ + double g = 60.0; + double h = 200.0; + double cal5 = 4094.0; + double j = -0.1; + double fclkm = 6.25; + + /* Mode2 temperature equation */ + return ((temp - g - j * fclkm) / h + 0.5) * cal5; +} + static uint32_t decode_pvt_volt(uint16_t volt) { double vref = 1.20; @@ -340,6 +357,70 @@ char *set_avalon8_freq(char *arg) return NULL; } +char *set_avalon8_freq_adjust_step(char *arg) +{ + int val, ret; + + ret = sscanf(arg, "%d", &val); + if (ret < 1) + return "No value passed to avalon8-freq-adjust-step"; + + if (val < AVA8_FREQ_ADJUST_LEVEL_MIX || val > AVA8_FREQ_ADJUST_LEVEL_MAX) + return "Invalid value passed to avalon8-freq-adjust-step"; + + opt_avalon8_freq_adjust_step = val * 25; + + return NULL; +} + +char *set_avalon8_voltage_level_adjust_step(char *arg) +{ + int val, ret; + + ret = sscanf(arg, "%d", &val); + if (ret < 1) + return "No value passed to avalon8-voltage-level-adjust-step"; + + if (val < AVA8_DEFAULT_VOLTAGE_LEVEL_MIN || val > AVA8_DEFAULT_VOLTAGE_LEVEL_MAX) + return "Invalid value passed to avalon8-voltage-level-adjust-step"; + + opt_avalon8_voltage_level_adjust_step = val; + + return NULL; +} + +char *set_avalon8_temp_add_freq_voltage(char *arg) +{ + int val, ret; + + ret = sscanf(arg, "%d", &val); + if (ret < 1) + return "No value passed to avalon8-temp-add-freq-voltage"; + + if (val < AVA8_TEMP_ADJUST_MIX || val > AVA8_TEMP_ADJUST_MAX) + return "Invalid value passed to avalon8-temp-add-freq-voltage"; + + opt_avalon8_temp_add_freq_voltage = encode_pvt_temp(val); + + return NULL; +} + +char *set_avalon8_temp_sub_freq_voltage(char *arg) +{ + int val, ret; + + ret = sscanf(arg, "%d", &val); + if (ret < 1) + return "No value passed to avalon8-temp-sub-freq-voltage"; + + if (val < AVA8_TEMP_ADJUST_MIX || val > AVA8_TEMP_ADJUST_MAX) + return "Invalid value passed to avalon8-temp-sub-freq-voltage"; + + opt_avalon8_temp_sub_freq_voltage = encode_pvt_temp(val); + + return NULL; +} + char *set_avalon8_voltage_level(char *arg) { int val, ret; @@ -1791,6 +1872,24 @@ static void avalon8_set_voltage_level(struct cgpu_info *avalon8, int addr, unsig avalon8->drv->name, avalon8->device_id, addr, i, voltage[0], voltage[info->miner_count[addr] - 1]); + tmp = be32toh(opt_avalon8_voltage_level_adjust_step); + memcpy(send_pkg.data + i * 4, &tmp, 4); + applog(LOG_DEBUG, "%s-%d-%d: avalon8 set voltage level adjust step %u", + avalon8->drv->name, avalon8->device_id, addr, + opt_avalon8_voltage_level_adjust_step); + + tmp = be32toh(opt_avalon8_temp_sub_freq_voltage); + memcpy(send_pkg.data + i * 4 + 4, &tmp, 4); + applog(LOG_DEBUG, "%s-%d-%d: avalon8 set temp sub freq and voltage %u", + avalon8->drv->name, avalon8->device_id, addr, + opt_avalon8_temp_sub_freq_voltage); + + tmp = be32toh(opt_avalon8_temp_add_freq_voltage); + memcpy(send_pkg.data + i * 4 + 8, &tmp, 4); + applog(LOG_DEBUG, "%s-%d-%d: avalon8 set temp add freq and voltage %u", + avalon8->drv->name, avalon8->device_id, addr, + opt_avalon8_temp_add_freq_voltage); + /* Package the data */ avalon8_init_pkg(&send_pkg, AVA8_P_SET_VOLT, 1, 1); if (addr == AVA8_MODULE_BROADCAST) @@ -1860,6 +1959,15 @@ static void avalon8_set_freq(struct cgpu_info *avalon8, int addr, int miner_id, avalon8->drv->name, avalon8->device_id, addr, miner_id, be32toh(tmp)); + if (opt_avalon8_freq_adjust_step % 25) + opt_avalon8_freq_adjust_step = 25; + + tmp = be32toh(opt_avalon8_freq_adjust_step); + memcpy(send_pkg.data + AVA8_DEFAULT_PLL_CNT * 4 + 8, &tmp, 4); + applog(LOG_DEBUG, "%s-%d-%d: avalon8 set freq adjust step %u", + avalon8->drv->name, avalon8->device_id, addr, + opt_avalon8_freq_adjust_step); + /* Package the data */ avalon8_init_pkg(&send_pkg, AVA8_P_SET_PLL, miner_id + 1, info->miner_count[addr]); @@ -2132,8 +2240,28 @@ static int64_t avalon8_scanhash(struct thr_info *thr) } if (update_settings) { cg_wlock(&info->update_lock); + + if (!strncmp((char *)&(info->mm_version[i]), "851", 3)) { + if (opt_avalon8_temp_add_freq_voltage == AVA8_INVALID_TEMP_ADD_FREQ_VOLTAGE) + opt_avalon8_temp_add_freq_voltage = AVA851_DEFAULT_TEMP_ADD_FREQ_VOLTAGE; + if (opt_avalon8_temp_sub_freq_voltage == AVA8_INVALID_TEMP_SUB_FREQ_VOLTAGE) + opt_avalon8_temp_sub_freq_voltage = AVA851_DEFAULT_TEMP_SUB_FREQ_VOLTAGE; + } else { + if (opt_avalon8_temp_add_freq_voltage == AVA8_INVALID_TEMP_ADD_FREQ_VOLTAGE) + opt_avalon8_temp_add_freq_voltage = AVA841_DEFAULT_TEMP_ADD_FREQ_VOLTAGE; + if (opt_avalon8_temp_sub_freq_voltage == AVA8_INVALID_TEMP_SUB_FREQ_VOLTAGE) + opt_avalon8_temp_sub_freq_voltage = AVA841_DEFAULT_TEMP_SUB_FREQ_VOLTAGE; + } avalon8_set_voltage_level(avalon8, i, info->set_voltage_level[i]); avalon8_set_asic_otp(avalon8, i, info->set_asic_otp[i]); + + if (!strncmp((char *)&(info->mm_version[i]), "851", 3)) { + if (opt_avalon8_freq_adjust_step == AVA8_INVALID_FREQ_ADJUST_STEP) + opt_avalon8_freq_adjust_step = AVA851_DEFAULT_FREQ_ADJUST_STEP; + } else { + if (opt_avalon8_freq_adjust_step == AVA8_INVALID_FREQ_ADJUST_STEP) + opt_avalon8_freq_adjust_step = AVA841_DEFAULT_FREQ_ADJUST_STEP; + } for (j = 0; j < info->miner_count[i]; j++) avalon8_set_freq(avalon8, i, j, info->set_frequency[i][j]); if (opt_avalon8_smart_speed) { diff --git a/driver-avalon8.h b/driver-avalon8.h index 4708661995..7f319f790f 100644 --- a/driver-avalon8.h +++ b/driver-avalon8.h @@ -103,6 +103,22 @@ #define AVA831_DEFAULT_SPDLOW 2 #define AVA831_DEFAULT_NONCE_MASK 27 +#define AVA8_DEFAULT_VOLT_ADJUST_STEP 3 +#define AVA8_INVALID_FREQ_ADJUST_STEP 1 +#define AVA841_DEFAULT_FREQ_ADJUST_STEP 100 +#define AVA851_DEFAULT_FREQ_ADJUST_STEP 0 +#define AVA8_INVALID_TEMP_SUB_FREQ_VOLTAGE 0 +#define AVA8_INVALID_TEMP_ADD_FREQ_VOLTAGE 0 +#define AVA841_DEFAULT_TEMP_SUB_FREQ_VOLTAGE 2612 /* 87 */ +#define AVA841_DEFAULT_TEMP_ADD_FREQ_VOLTAGE 2469 /* 80 */ +#define AVA851_DEFAULT_TEMP_SUB_FREQ_VOLTAGE 2776 /* 95 */ +#define AVA851_DEFAULT_TEMP_ADD_FREQ_VOLTAGE 2673 /* 90 */ + +#define AVA8_TEMP_ADJUST_MIX 60 +#define AVA8_TEMP_ADJUST_MAX 100 +#define AVA8_FREQ_ADJUST_LEVEL_MIX 1 +#define AVA8_FREQ_ADJUST_LEVEL_MAX 4 + #define AVA8_DEFAULT_IIC_DETECT false #define AVA8_PWM_MAX 0x3FF @@ -356,6 +372,10 @@ struct avalon8_dev_description { extern char *set_avalon8_fan(char *arg); extern char *set_avalon8_freq(char *arg); extern char *set_avalon8_voltage_level(char *arg); +extern char *set_avalon8_freq_adjust_step(char *arg); +extern char *set_avalon8_voltage_level_adjust_step(char *arg); +extern char *set_avalon8_temp_add_freq_voltage(char *arg); +extern char *set_avalon8_temp_sub_freq_voltage(char *arg); extern char *set_avalon8_voltage_level_offset(char *arg); extern int opt_avalon8_temp_target; extern int opt_avalon8_polling_delay;