Browse Source

jingtian: Do detection asynchronously across all possible chipselects so they complete in parallel

Luke Dashjr 11 years ago
parent
commit
d7faf33eb8
3 changed files with 95 additions and 35 deletions
  1. 60 16
      driver-aan.c
  2. 1 1
      driver-aan.h
  3. 34 18
      driver-jingtian.c

+ 60 - 16
driver-aan.c

@@ -96,25 +96,69 @@ bool aan_spi_cmd(struct spi_port * const spi, const uint8_t cmd, const uint8_t c
 	return true;
 	return true;
 }
 }
 
 
-static
-int aan_spi_autoaddress(struct spi_port * const spi, const struct timeval * const tvp_timeout)
-{
-	if (!aan_spi_cmd(spi, AAN_BIST_START, AAN_ALL_CHIPS, NULL, 0, tvp_timeout))
-		applogr(-1, LOG_DEBUG, "%s: %s failed", __func__, "AAN_BIST_START");
-	spi_emit_nop(spi, 2);
-	if (!spi_txrx(spi))
-		applogr(-1, LOG_DEBUG, "%s: %s failed", __func__, "spi_txrx");
-	uint8_t * const rx = spi_getrxbuf(spi);
-	return rx[1];
-}
-
-int aan_detect_spi(struct spi_port * const spi)
+int aan_detect_spi(int * const out_chipcount, struct spi_port * const * const spi_a, const int spi_n)
 {
 {
 	struct timeval tv_timeout;
 	struct timeval tv_timeout;
 	timer_set_delay_from_now(&tv_timeout, AAN_PROBE_TIMEOUT_US);
 	timer_set_delay_from_now(&tv_timeout, AAN_PROBE_TIMEOUT_US);
-	if (!aan_spi_cmd(spi, AAN_RESET, AAN_ALL_CHIPS, NULL, 0, &tv_timeout))
-		return -1;
-	return aan_spi_autoaddress(spi, &tv_timeout);
+	
+	int state[spi_n];
+	int completed = 0;
+	
+	for (int i = 0; i < spi_n; ++i)
+	{
+		struct spi_port * const spi = spi_a[i];
+		aan_spi_cmd_send(spi, state[i] = AAN_RESET, AAN_ALL_CHIPS, NULL, 0);
+		spi_emit_nop(spi, 2);
+		out_chipcount[i] = -1;
+	}
+	
+	do {
+		for (int i = 0; i < spi_n; ++i)
+		{
+			if (state[i] == -1)
+				continue;
+			struct spi_port * const spi = spi_a[i];
+			if (unlikely(!spi_txrx(spi)))
+			{
+spifail:
+				state[i] = -1;
+				continue;
+			}
+			uint8_t * const rx = spi_getrxbuf(spi);
+			if (rx[0] == state[i] && rx[1] == AAN_ALL_CHIPS)
+			{
+				switch (state[i])
+				{
+					case AAN_RESET:
+						applog(LOG_DEBUG, "%s: Reset complete", spi->repr);
+						spi_clear_buf(spi);
+						aan_spi_cmd_send(spi, state[i] = AAN_BIST_START, AAN_ALL_CHIPS, NULL, 0);
+						spi_emit_nop(spi, 2);
+						break;
+					case AAN_BIST_START:
+						if (unlikely(!spi_txrx(spi)))
+							goto spifail;
+						out_chipcount[i] = rx[1];
+						state[i] = -1;
+						++completed;
+						applog(LOG_DEBUG, "%s: BIST_START complete (%d chips)", spi->repr, rx[1]);
+						break;
+				}
+				continue;
+			}
+			aan_spi_parse_rx(spi);
+		}
+	} while (completed < spi_n && likely(!timer_passed(&tv_timeout, NULL)));
+	
+	for (int i = 0; i < spi_n; ++i)
+	{
+		struct spi_port * const spi = spi_a[i];
+		spi_clear_buf(spi);
+	}
+	
+	applog(LOG_DEBUG, "%s completed for %d out of %d SPI ports", __func__, completed, spi_n);
+	
+	return completed;
 }
 }
 
 
 static
 static

+ 1 - 1
driver-aan.h

@@ -9,6 +9,6 @@ struct aan_hooks {
 	void (*precmd)(struct spi_port *);
 	void (*precmd)(struct spi_port *);
 };
 };
 
 
-extern int aan_detect_spi(struct spi_port *);
+extern int aan_detect_spi(int *out_chipcount, struct spi_port * const *spi_a, int spi_n);
 
 
 #endif
 #endif

+ 34 - 18
driver-jingtian.c

@@ -105,40 +105,56 @@ bool jingtian_detect_one(const char * const devpath)
 		applogr(false, LOG_DEBUG, "%s: Failed to open %s", jingtian_drv.dname, devpath);
 		applogr(false, LOG_DEBUG, "%s: Failed to open %s", jingtian_drv.dname, devpath);
 	
 	
 	struct cgpu_info *cgpu, *prev_cgpu = NULL;
 	struct cgpu_info *cgpu, *prev_cgpu = NULL;
-	struct spi_port * const spi = calloc(sizeof(*spi), 1), *spicopy;
-	spi->txrx = jingtian_spi_txrx;
-	spi->userp = &jingtian_hooks;
-	spi->fd = fd;
-	spi->speed = 4000000;
-	spi->delay = 0;
-	spi->mode = 1;
-	spi->bits = 8;
-	spi->chipselect_current = malloc(sizeof(*spi->chipselect_current));
-	*spi->chipselect_current = -1;
+	struct spi_port *spi;
+	int * const chipselect_current = malloc(sizeof(*spi->chipselect_current));
+	*chipselect_current = -1;
+	
+	int devpath_len = strlen(devpath);
+	
+	int chipcount[jingtian_max_cs];
+	struct spi_port *spi_a[jingtian_max_cs];
 	for (int i = 0; i < jingtian_max_cs; ++i)
 	for (int i = 0; i < jingtian_max_cs; ++i)
 	{
 	{
+		spi = spi_a[i] = calloc(sizeof(*spi), 1);
+		spi->repr = malloc(devpath_len + 0x10);
+		sprintf((void*)spi->repr, "%s(cs%d)", devpath, i);
+		spi->txrx = jingtian_spi_txrx;
+		spi->userp = &jingtian_hooks;
+		spi->fd = fd;
+		spi->speed = 4000000;
+		spi->delay = 0;
+		spi->mode = 1;
+		spi->bits = 8;
 		spi->chipselect = i;
 		spi->chipselect = i;
-		chips = aan_detect_spi(spi);
-		applog(LOG_DEBUG, "%s: %d chips found on %s CS %d",
-		       jingtian_drv.dname, chips, devpath, i);
+		spi->chipselect_current = chipselect_current;
+	}
+	
+	aan_detect_spi(chipcount, spi_a, jingtian_max_cs);
+	
+	for (int i = 0; i < jingtian_max_cs; ++i)
+	{
+		chips = chipcount[i];
+		free((void*)spi_a[i]->repr);
+		spi_a[i]->repr = NULL;
 		if (chips <= 0)
 		if (chips <= 0)
+		{
+			free(spi_a[i]);
 			continue;
 			continue;
-		spicopy = malloc(sizeof(*spicopy));
-		memcpy(spicopy, spi, sizeof(*spicopy));
+		}
 		cgpu = malloc(sizeof(*cgpu));
 		cgpu = malloc(sizeof(*cgpu));
 		*cgpu = (struct cgpu_info){
 		*cgpu = (struct cgpu_info){
 			.drv = &jingtian_drv,
 			.drv = &jingtian_drv,
 			.procs = chips,
 			.procs = chips,
-			.device_data = spicopy,
+			.device_data = spi_a[i],
 		};
 		};
 		add_cgpu_slave(cgpu, prev_cgpu);
 		add_cgpu_slave(cgpu, prev_cgpu);
 		prev_cgpu = cgpu;
 		prev_cgpu = cgpu;
 		found += chips;
 		found += chips;
 	}
 	}
+	
 	close(fd);
 	close(fd);
 	if (!found)
 	if (!found)
-		free(spi->chipselect_current);
-	free(spi);
+		free(chipselect_current);
 	return found;
 	return found;
 }
 }