Browse Source

jingtian: Detection-only code for new driver

Luke Dashjr 11 years ago
parent
commit
c4db994e9f
6 changed files with 263 additions and 0 deletions
  1. 5 0
      Makefile.am
  2. 14 0
      configure.ac
  3. 82 0
      driver-aan.c
  4. 14 0
      driver-aan.h
  5. 146 0
      driver-jingtian.c
  6. 2 0
      lowl-spi.h

+ 5 - 0
Makefile.am

@@ -320,6 +320,11 @@ if USE_HASHFAST
 bfgminer_SOURCES += driver-hashfast.c
 bfgminer_SOURCES += driver-hashfast.c
 endif
 endif
 
 
+if USE_JINGTIAN
+bfgminer_SOURCES += driver-aan.c driver-aan.h
+bfgminer_SOURCES += driver-jingtian.c
+endif
+
 if USE_ROCKMINER
 if USE_ROCKMINER
 bfgminer_SOURCES += driver-rockminer.c
 bfgminer_SOURCES += driver-rockminer.c
 endif
 endif

+ 14 - 0
configure.ac

@@ -1021,6 +1021,20 @@ fi
 AM_CONDITIONAL([USE_HASHFAST], [test x$hashfast = xyes])
 AM_CONDITIONAL([USE_HASHFAST], [test x$hashfast = xyes])
 
 
 
 
+driverlist="$driverlist jingtian"
+AC_ARG_ENABLE([jingtian],
+	[AC_HELP_STRING([--enable-jingtian],[Compile support for JingTian (default disabled)])],
+	[jingtian=$enableval],
+	[jingtian=$ddno]
+	)
+if test "x$jingtian" = "xyes"; then
+	AC_DEFINE([USE_JINGTIAN], [1], [Defined to 1 if JingTian support is wanted])
+	need_lowl_spi=yes
+	has_asic=yes
+fi
+AM_CONDITIONAL([USE_JINGTIAN], [test x$jingtian = xyes])
+
+
 driverlist="$driverlist metabank"
 driverlist="$driverlist metabank"
 AC_ARG_ENABLE([metabank],
 AC_ARG_ENABLE([metabank],
 	[AC_HELP_STRING([--enable-metabank],[Compile support for Metabank (default disabled)])],
 	[AC_HELP_STRING([--enable-metabank],[Compile support for Metabank (default disabled)])],

+ 82 - 0
driver-aan.c

@@ -0,0 +1,82 @@
+/*
+ * Copyright 2014 Luke Dashjr
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.  See COPYING for more details.
+ */
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "driver-aan.h"
+#include "logging.h"
+#include "lowl-spi.h"
+#include "miner.h"
+#include "util.h"
+
+#define AAN_PROBE_TIMEOUT_US  3750000
+
+enum aan_cmd {
+	AAN_BIST_START           = 0x01,
+	AAN_BIST_FIX             = 0x03,
+	AAN_RESET                = 0x04,
+	AAN_WRITE_JOB            = 0x07,
+	AAN_READ_RESULT          = 0x08,
+	AAN_WRITE_REG            = 0x09,
+	AAN_READ_REG             = 0x0a,
+	AAN_READ_REG_RESP        = 0x1a,
+};
+
+static
+bool aan_spi_cmd(struct spi_port * const spi, const uint8_t cmd, const uint8_t chip, const struct timeval * const tvp_timeout)
+{
+	const struct aan_hooks * const hooks = spi->userp;
+	const uint8_t cmdbuf[2] = {cmd, chip};
+	hooks->precmd(spi);
+	spi_emit_buf(spi, cmdbuf, sizeof(cmdbuf));
+	if (unlikely(!spi_txrx(spi)))
+		return false;
+	
+	spi_clear_buf(spi);
+	spi_emit_nop(spi, 2);
+	
+	uint8_t * const rx = spi_getrxbuf(spi);
+	while (true)
+	{
+		if (unlikely(!spi_txrx(spi)))
+			return false;
+		if (!memcmp(rx, cmdbuf, 2))
+			break;
+		if (unlikely(tvp_timeout && timer_passed(tvp_timeout, NULL)))
+			return false;
+	}
+	spi_clear_buf(spi);
+	
+	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, 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)
+{
+	struct timeval tv_timeout;
+	timer_set_delay_from_now(&tv_timeout, AAN_PROBE_TIMEOUT_US);
+	if (!aan_spi_cmd(spi, AAN_RESET, AAN_ALL_CHIPS, &tv_timeout))
+		return -1;
+	return aan_spi_autoaddress(spi, &tv_timeout);
+}

+ 14 - 0
driver-aan.h

@@ -0,0 +1,14 @@
+#ifndef BFG_DRIVER_AAN
+#define BFG_DRIVER_AAN
+
+#include "lowl-spi.h"
+
+#define AAN_ALL_CHIPS  0
+
+struct aan_hooks {
+	void (*precmd)(struct spi_port *);
+};
+
+extern int aan_detect_spi(struct spi_port *);
+
+#endif

+ 146 - 0
driver-jingtian.c

@@ -0,0 +1,146 @@
+/*
+ * Copyright 2014 Luke Dashjr
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option)
+ * any later version.  See COPYING for more details.
+ */
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "deviceapi.h"
+#include "driver-aan.h"
+#include "logging.h"
+#include "lowl-spi.h"
+#include "util.h"
+
+static const int jingtian_cs_gpio[] = {14, 15, 18};
+static const int jingtian_max_cs = 1 << (sizeof(jingtian_cs_gpio) / sizeof(*jingtian_cs_gpio));
+static const uint8_t jingtian_pre_header[] = {0xb5, 0xb5};
+
+BFG_REGISTER_DRIVER(jingtian_drv)
+
+static
+bool jingtian_spi_txrx(struct spi_port * const port)
+{
+	if (*port->chipselect_current != port->chipselect)
+	{
+		unsigned cs_set_low = 0, cs_set_high = 0, cur_cs_bit;
+		bool bit_desired;
+		for (int i = 0; i < sizeof(jingtian_cs_gpio) / sizeof(*jingtian_cs_gpio); ++i)
+		{
+			cur_cs_bit = (1 << i);
+			bit_desired = (port->chipselect & cur_cs_bit);
+			if (bit_desired == (bool)(*port->chipselect_current & cur_cs_bit))
+				// No change needed
+				continue;
+			if (bit_desired)
+				cs_set_high |= (1 << jingtian_cs_gpio[i]);
+			else
+				cs_set_low  |= (1 << jingtian_cs_gpio[i]);
+		}
+		if (cs_set_low)
+			bfg_gpio_set_low(cs_set_low);
+		if (cs_set_high)
+			bfg_gpio_set_high(cs_set_high);
+		*port->chipselect_current = port->chipselect;
+	}
+	return linux_spi_txrx(port);
+}
+
+static
+void jingtian_precmd(struct spi_port * const spi)
+{
+	spi_emit_buf(spi, jingtian_pre_header, sizeof(jingtian_pre_header));
+}
+
+static
+struct aan_hooks jingtian_hooks = {
+	.precmd = jingtian_precmd,
+};
+
+static
+void jingtian_common_init(void)
+{
+	RUNONCE();
+	spi_init();
+	for (int i = 0; i < sizeof(jingtian_cs_gpio) / sizeof(*jingtian_cs_gpio); ++i)
+		bfg_gpio_setpin_output(jingtian_cs_gpio[i]);
+}
+
+static
+bool jingtian_detect_one(const char * const devpath)
+{
+	int found = 0, chips;
+	
+	jingtian_common_init();
+	
+	const int fd = open(devpath, O_RDWR);
+	if (fd < 0)
+		applogr(false, LOG_DEBUG, "%s: Failed to open %s", jingtian_drv.dname, devpath);
+	
+	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;
+	for (int i = 0; i < jingtian_max_cs; ++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);
+		if (chips <= 0)
+			continue;
+		spicopy = malloc(sizeof(*spicopy));
+		memcpy(spicopy, spi, sizeof(*spicopy));
+		cgpu = malloc(sizeof(*cgpu));
+		*cgpu = (struct cgpu_info){
+			.drv = &jingtian_drv,
+			.procs = chips,
+			.device_data = spicopy,
+		};
+		add_cgpu_slave(cgpu, prev_cgpu);
+		prev_cgpu = cgpu;
+		found += chips;
+	}
+	close(fd);
+	if (!found)
+		free(spi->chipselect_current);
+	free(spi);
+	return found;
+}
+
+static
+int jingtian_detect_auto(void)
+{
+	return jingtian_detect_one("/dev/spidev0.0") ? 1 : 0;
+}
+
+static
+void jingtian_detect(void)
+{
+	generic_detect(&jingtian_drv, jingtian_detect_one, jingtian_detect_auto, GDF_REQUIRE_DNAME | GDF_DEFAULT_NOAUTO);
+}
+
+struct device_drv jingtian_drv = {
+	.dname = "jingtian",
+	.name = "JTN",
+	.drv_detect = jingtian_detect,
+};

+ 2 - 0
lowl-spi.h

@@ -36,6 +36,8 @@ struct spi_port {
 	uint16_t delay;
 	uint16_t delay;
 	uint8_t mode;
 	uint8_t mode;
 	uint8_t bits;
 	uint8_t bits;
+	int chipselect;
+	int *chipselect_current;
 };
 };
 
 
 extern struct spi_port *sys_spi;
 extern struct spi_port *sys_spi;