Browse Source

alchemist: Experimental USB->UART Dongle Support on RPi

This adds preliminary support to run alcheminer boards using USB->UART
dongle boards.

In order for this to work, the reset pin on the alchemic board must be
connected to the RTS pin on the dongle board, and option --set
ALC:mode=1 added to startup command line.
John 9 years ago
parent
commit
bc58611b6b
1 changed files with 78 additions and 41 deletions
  1. 78 41
      driver-alchemist.c

+ 78 - 41
driver-alchemist.c

@@ -59,6 +59,7 @@ struct alchemist_chip {
 	uint32_t clst_offset[alchemist_max_clusters_per_chip];
 	unsigned active_cores;
 	unsigned freq;
+	unsigned reset_mode;
 };
 
 static
@@ -71,49 +72,64 @@ void alchemist_chip_init(struct alchemist_chip * const chip, const uint8_t chipi
 		.clst_offset = {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 		.active_cores = 1728,
 		.freq = ALCHEMIST_DEFAULT_FREQUENCY,
+		.reset_mode = 0,
 	};
 }
 
 static
-void alchemist_reset_board(const char * const devpath)
+void alchemist_reset_board(const char * const devpath, struct alchemist_chip * const chip, const int fd)
 {
-	char gpio[8];
-	int fd;
-	char buf[50];
-	
-	// TODO: allow custom reset pin through --set for non-stock controller
-	if (strcmp(devpath, "/dev/ttyO1") == 0)
-		strcpy(gpio, "gpio117");
-	else if (strcmp(devpath, "/dev/ttyO2") == 0)
-		strcpy(gpio, "gpio110");
-	else if (strcmp(devpath, "/dev/ttyO3") == 0)
-		strcpy(gpio, "gpio111");
-	else if (strcmp(devpath, "/dev/ttyO4") == 0)
-		strcpy(gpio, "gpio112");
-	else if (strcmp(devpath, "/dev/ttyUSB0") == 0)
-		strcpy(gpio, "gpio113");
-	else if (strcmp(devpath, "/dev/ttyUSB1") == 0)
-		strcpy(gpio, "gpio114");
-	else if (strcmp(devpath, "/dev/ttyUSB2") == 0)
-		strcpy(gpio, "gpio115");
-	else if (strcmp(devpath, "/dev/ttyUSB3") == 0)
-		strcpy(gpio, "gpio116");
-	else if (strcmp(devpath, "/dev/ttyAMA0") == 0)
-		strcpy(gpio, "gpio25");
-	else
-		return;
-	
-	sprintf(buf, "/sys/class/gpio/%s/value", gpio);
-	
-	fd = open(buf, O_WRONLY);
-	
-	if (write(fd, "0", 1) != 1)
-		applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "GPIO write error", devpath);
-	cgsleep_ms(100);
-	if (write(fd, "1", 1) != 1)
-		applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "GPIO write error", devpath);
-	
-	close(fd);
+	if (chip->reset_mode == 0) {
+		char gpio[8];
+		int fd;
+		char buf[50];
+		
+		// TODO: allow custom reset pin through --set for non-stock controller
+		if (strcmp(devpath, "/dev/ttyO1") == 0)
+			strcpy(gpio, "gpio117");
+		else if (strcmp(devpath, "/dev/ttyO2") == 0)
+			strcpy(gpio, "gpio110");
+		else if (strcmp(devpath, "/dev/ttyO3") == 0)
+			strcpy(gpio, "gpio111");
+		else if (strcmp(devpath, "/dev/ttyO4") == 0)
+			strcpy(gpio, "gpio112");
+		else if (strcmp(devpath, "/dev/ttyUSB0") == 0)
+			strcpy(gpio, "gpio113");
+		else if (strcmp(devpath, "/dev/ttyUSB1") == 0)
+			strcpy(gpio, "gpio114");
+		else if (strcmp(devpath, "/dev/ttyUSB2") == 0)
+			strcpy(gpio, "gpio115");
+		else if (strcmp(devpath, "/dev/ttyUSB3") == 0)
+			strcpy(gpio, "gpio116");
+		else if (strcmp(devpath, "/dev/ttyAMA0") == 0)
+			strcpy(gpio, "gpio25");
+		else
+			return;
+		
+		sprintf(buf, "/sys/class/gpio/%s/value", gpio);
+		
+		fd = open(buf, O_WRONLY);
+		
+		if (write(fd, "0", 1) != 1)
+			applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "GPIO write error", devpath);
+		cgsleep_ms(100);
+		if (write(fd, "1", 1) != 1)
+			applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "GPIO write error", devpath);
+		
+		close(fd);
+	} else {
+		applog(LOG_DEBUG, "START IOCTL RTS RESET");
+		
+		if (set_serial_rts(fd, BGV_HIGH) == BGV_ERROR) {
+			applog(LOG_DEBUG, "IOCTL RTS RESET FAILED");
+		}
+		
+		cgsleep_ms(100);
+		
+		if (set_serial_rts(fd, BGV_LOW) == BGV_ERROR) {
+			applog(LOG_DEBUG, "IOCTL RTS RESET FAILED");
+		}
+	}
 }
 
 static
@@ -265,7 +281,6 @@ bool alchemist_detect_one(const char * const devpath)
 	
 	applog(LOG_DEBUG, "%s: %s %s", alchemist_drv.dname, "Successfully opened", devpath);
 	
-	alchemist_reset_board(devpath);
 	
 	// Init chips, setup PLL, and scan for good cores
 	chips = malloc(alchemist_max_chips * sizeof(*chips));
@@ -277,8 +292,12 @@ bool alchemist_detect_one(const char * const devpath)
 	drv_set_defaults(&alchemist_drv, alchemist_set_device_funcs_probe, dummy_chip, devpath, detectone_meta_info.serial, 1);
 	
 	unsigned freq = dummy_chip->freq;
+	unsigned mode = dummy_chip->reset_mode;
 	
 	unsigned total_cores = 0;
+	
+	alchemist_reset_board(devpath, dummy_chip, fd);
+	
 	{
 		uint8_t buf[9];
 		for (unsigned i = 0; i < alchemist_max_chips; ++i)
@@ -286,6 +305,7 @@ bool alchemist_detect_one(const char * const devpath)
 			struct alchemist_chip * const chip = &chips[i];
 			alchemist_chip_init(chip, i);
 			chip->freq = freq;
+			chip->reset_mode = mode;
 			alchemist_set_diag_mode(chip, true);
 			if (!alchemist_init_pll(fd, chip))
 				return_via_applog(err, , LOG_DEBUG, "%s: Failed to (%s) %s", alchemist_drv.dname, "init PLL", devpath);
@@ -319,7 +339,7 @@ bool alchemist_detect_one(const char * const devpath)
 	if (!total_cores)
 		goto err;
 	
-	alchemist_reset_board(devpath);
+	alchemist_reset_board(devpath, dummy_chip, fd);
 	
 	// config nonce ranges per cluster based on core responses
 	unsigned mutiple = ALCHEMIST_MAX_NONCE / total_cores;
@@ -486,8 +506,9 @@ static
 void alchemist_thread_shutdown(struct thr_info *thr)
 {
 	struct cgpu_info *device = thr->cgpu;
+	struct alchemist_chip *chips = device->device_data;
 	
-	alchemist_reset_board(device->device_path);
+	alchemist_reset_board(device->device_path, &chips[0], device->device_fd);
 	
 	serial_close(device->device_fd);
 }
@@ -517,9 +538,25 @@ const char *alchemist_set_clock(struct cgpu_info * const device, const char * co
 	return NULL;
 }
 
+static
+const char *alchemist_set_mode(struct cgpu_info * const device, const char * const option, const char * const setting, char * const replybuf, enum bfg_set_device_replytype * const success)
+{
+	struct alchemist_chip * const chip = device->device_data;
+	int val = atoi(setting);
+	
+	if (val == 1) {
+		chip->reset_mode = val;
+		sprintf(replybuf, "Driver mode set to raspery pi controller using USB->UART Dongles");
+		return replybuf;
+	}
+	
+	return NULL;
+}
+
 static
 const struct bfg_set_device_definition alchemist_set_device_funcs_probe[] = {
 	{ "clock", alchemist_set_clock, NULL },
+	{ "mode", alchemist_set_mode, NULL },
 	{ NULL },
 };