Browse Source

Merge branch 'knc' into bfgminer

Luke Dashjr 12 years ago
parent
commit
38865a402d
1 changed files with 99 additions and 8 deletions
  1. 99 8
      driver-knc.c

+ 99 - 8
driver-knc.c

@@ -16,6 +16,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <math.h>
 
 #ifdef HAVE_LINUX_I2C_DEV_USER_H
 #include <linux/i2c-dev-user.h>
@@ -70,6 +71,9 @@ struct knc_device {
 struct knc_core {
 	int asicno;
 	int coreno;
+	
+	float volt;
+	float current;
 };
 
 static
@@ -568,19 +572,36 @@ void knc_core_enable(struct thr_info * const thr)
 	_knc_core_setstatus(thr, 1);
 }
 
+static
+float knc_dcdc_decode_5_11(uint16_t raw)
+{
+	if (raw == 0)
+		return 0.0;
+	
+	int dcdc_vin_exp = (raw & 0xf800) >> 11;
+	float dcdc_vin_man = raw & 0x07ff;
+	if (dcdc_vin_exp >= 16)
+		dcdc_vin_exp = -32 + dcdc_vin_exp;
+	float dcdc_vin = dcdc_vin_man * exp2(dcdc_vin_exp);
+	return dcdc_vin;
+}
+
 static
 bool knc_get_stats(struct cgpu_info * const cgpu)
 {
 	if (cgpu->device != cgpu)
 		return true;
 	
-	struct knc_core * const knccore = cgpu->thr[0]->cgpu_data;
+	struct thr_info *thr = cgpu->thr[0];
+	struct knc_core *knccore = thr->cgpu_data;
 	struct cgpu_info *proc;
 	const int i2cdev = knccore->asicno + 3;
-	const int i2cslave = 0x48;
+	const int i2cslave_temp = 0x48;
+	const int i2cslave_dcdc[] = {0x10, 0x12, 0x14, 0x17};
+	int die, i;
 	int i2c;
-	int32_t rawtemp;
-	float temp;
+	int32_t rawtemp, rawvolt, rawcurrent;
+	float temp, volt, current;
 	bool rv = false;
 	
 	char i2cpath[sizeof(KNC_I2C_TEMPLATE)];
@@ -593,10 +614,10 @@ bool knc_get_stats(struct cgpu_info * const cgpu)
 		return false;
 	}
 	
-	if (ioctl(i2c, I2C_SLAVE, i2cslave))
+	if (ioctl(i2c, I2C_SLAVE, i2cslave_temp))
 	{
 		applog(LOG_DEBUG, "%s: %s: Failed to select i2c slave 0x%x",
-		       cgpu->dev_repr, __func__, i2cslave);
+		       cgpu->dev_repr, __func__, i2cslave_temp);
 		goto out;
 	}
 	
@@ -604,11 +625,52 @@ bool knc_get_stats(struct cgpu_info * const cgpu)
 	if (rawtemp == -1)
 		goto out;
 	temp = ((float)(rawtemp & 0xff));
-	if (rawtemp & 0x100)
+	if (rawtemp & 0x8000)
 		temp += 0.5;
 	
-	for (proc = cgpu; proc && proc->device == cgpu; proc = proc->next_proc)
+	/* DCDC i2c slaves are on 0x10 + [0-7]
+	   8 DCDC boards have all populated
+	   4 DCDC boards only have 0,2,4,7 populated
+	   Only 0,2,4,7 are used
+	   Each DCDC powers one die in the chip, each die has 48 cores
+	   
+	   Datasheet at http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
+	*/
+
+	for (proc = cgpu, i = 0; proc && proc->device == cgpu; proc = proc->next_proc, ++i)
+	{
+		thr = proc->thr[0];
+		knccore = thr->cgpu_data;
+		die = i / 0x30;
+		
+		if (0 == i % 0x30)
+		{
+			if (ioctl(i2c, I2C_SLAVE, i2cslave_dcdc[die]))
+			{
+				applog(LOG_DEBUG, "%s: %s: Failed to select i2c slave 0x%x",
+				       cgpu->dev_repr, __func__, i2cslave_dcdc[die]);
+				goto out;
+			}
+			
+			rawvolt = i2c_smbus_read_word_data(i2c, 0x8b);  // VOUT
+			if (rawvolt == -1)
+				goto out;
+			
+			rawcurrent = i2c_smbus_read_word_data(i2c, 0x8c);  // IOUT
+			if (rawcurrent == -1)
+				goto out;
+			
+			volt    = (float)rawvolt * exp2(-10);
+			current = (float)knc_dcdc_decode_5_11(rawcurrent);
+			
+			applog(LOG_DEBUG, "%s: die %d %6.3fV %5.2fA",
+			       cgpu->dev_repr, die, volt, current);
+		}
+		
 		proc->temp = temp;
+		knccore->volt = volt;
+		knccore->current = current;
+	}
 	
 	rv = true;
 out:
@@ -616,6 +678,31 @@ out:
 	return rv;
 }
 
+static
+struct api_data *knc_api_extra_device_status(struct cgpu_info * const cgpu)
+{
+	struct api_data *root = NULL;
+	struct thr_info * const thr = cgpu->thr[0];
+	struct knc_core * const knccore = thr->cgpu_data;
+	
+	root = api_add_volts(root, "Voltage", &knccore->volt, false);
+	root = api_add_volts(root, "DCDC Current", &knccore->current, false);
+	
+	return root;
+}
+
+#ifdef HAVE_CURSES
+static
+void knc_wlogprint_status(struct cgpu_info * const cgpu)
+{
+	struct thr_info * const thr = cgpu->thr[0];
+	struct knc_core * const knccore = thr->cgpu_data;
+	
+	wlogprint("Voltage: %.3f  DCDC Current: %.3f\n",
+	          knccore->volt, knccore->current);
+}
+#endif
+
 struct device_drv knc_drv = {
 	.dname = "knc",
 	.name = "KNC",
@@ -631,4 +718,8 @@ struct device_drv knc_drv = {
 	.poll = knc_poll,
 	
 	.get_stats = knc_get_stats,
+	.get_api_extra_device_status = knc_api_extra_device_status,
+#ifdef HAVE_CURSES
+	.proc_wlogprint_status = knc_wlogprint_status,
+#endif
 };