|
@@ -63,6 +63,16 @@ void checksum(uint8_t *b, uint8_t bits)
|
|
|
b[i/8] |= 0x80 >> (i % 8);
|
|
b[i/8] |= 0x80 >> (i % 8);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static
|
|
|
|
|
+void x6500_jtag_set(struct jtag_port *jp, uint8_t pinoffset)
|
|
|
|
|
+{
|
|
|
|
|
+ jp->tck = pinoffset << 3;
|
|
|
|
|
+ jp->tms = pinoffset << 2;
|
|
|
|
|
+ jp->tdi = pinoffset << 1;
|
|
|
|
|
+ jp->tdo = pinoffset << 0;
|
|
|
|
|
+ jp->ignored = ~(jp->tdo | jp->tdi | jp->tms | jp->tck);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static
|
|
static
|
|
|
void x6500_set_register(struct jtag_port *jp, uint8_t addr, uint32_t nv)
|
|
void x6500_set_register(struct jtag_port *jp, uint8_t addr, uint32_t nv)
|
|
|
{
|
|
{
|
|
@@ -174,23 +184,26 @@ x6500_fpga_upload_bitstream(struct cgpu_info *x6500, struct jtag_port *jp1)
|
|
|
// "Magic" jtag_port configured to access both FPGAs concurrently
|
|
// "Magic" jtag_port configured to access both FPGAs concurrently
|
|
|
struct jtag_port jpt = {
|
|
struct jtag_port jpt = {
|
|
|
.a = jp1->a,
|
|
.a = jp1->a,
|
|
|
- .tck = 0x88,
|
|
|
|
|
- .tms = 0x44,
|
|
|
|
|
- .tdi = 0x22,
|
|
|
|
|
- .tdo = 0x11,
|
|
|
|
|
- .ignored = 0,
|
|
|
|
|
};
|
|
};
|
|
|
struct jtag_port *jp = &jpt;
|
|
struct jtag_port *jp = &jpt;
|
|
|
- uint8_t i;
|
|
|
|
|
|
|
+ uint8_t i, j;
|
|
|
|
|
+ x6500_jtag_set(jp, 0x11);
|
|
|
|
|
|
|
|
// Need to reset here despite previous FPGA state, since we are programming all at once
|
|
// Need to reset here despite previous FPGA state, since we are programming all at once
|
|
|
jtag_reset(jp);
|
|
jtag_reset(jp);
|
|
|
|
|
|
|
|
jtag_write(jp, JTAG_REG_IR, "\xd0", 6); // JPROGRAM
|
|
jtag_write(jp, JTAG_REG_IR, "\xd0", 6); // JPROGRAM
|
|
|
- do {
|
|
|
|
|
- i = 0xd0; // Re-set JPROGRAM while reading status
|
|
|
|
|
- jtag_read(jp, JTAG_REG_IR, &i, 6);
|
|
|
|
|
- } while (i & 8);
|
|
|
|
|
|
|
+ // Poll each FPGA status individually since they might not be ready at the same time
|
|
|
|
|
+ for (j = 0; j < 2; ++j) {
|
|
|
|
|
+ x6500_jtag_set(jp, j ? 0x10 : 1);
|
|
|
|
|
+ do {
|
|
|
|
|
+ i = 0xd0; // Re-set JPROGRAM while reading status
|
|
|
|
|
+ jtag_read(jp, JTAG_REG_IR, &i, 6);
|
|
|
|
|
+ } while (i & 8);
|
|
|
|
|
+ applog(LOG_DEBUG, "%s %u.%u: JPROGRAM ready",
|
|
|
|
|
+ x6500->api->name, x6500->device_id, j);
|
|
|
|
|
+ }
|
|
|
|
|
+ x6500_jtag_set(jp, 0x11);
|
|
|
jtag_write(jp, JTAG_REG_IR, "\xa0", 6); // CFG_IN
|
|
jtag_write(jp, JTAG_REG_IR, "\xa0", 6); // CFG_IN
|
|
|
|
|
|
|
|
sleep(1);
|
|
sleep(1);
|
|
@@ -264,11 +277,7 @@ static bool x6500_fpga_init(struct thr_info *thr)
|
|
|
fpga = calloc(1, sizeof(*fpga));
|
|
fpga = calloc(1, sizeof(*fpga));
|
|
|
jp = &fpga->jtag;
|
|
jp = &fpga->jtag;
|
|
|
jp->a = x6500->cgpu_data;
|
|
jp->a = x6500->cgpu_data;
|
|
|
- jp->tck = pinoffset << 3;
|
|
|
|
|
- jp->tms = pinoffset << 2;
|
|
|
|
|
- jp->tdi = pinoffset << 1;
|
|
|
|
|
- jp->tdo = pinoffset << 0;
|
|
|
|
|
- jp->ignored = ~(fpga->jtag.tdo | fpga->jtag.tdi | fpga->jtag.tms | fpga->jtag.tck);
|
|
|
|
|
|
|
+ x6500_jtag_set(jp, pinoffset);
|
|
|
|
|
|
|
|
mutex_lock(&x6500->device_mutex);
|
|
mutex_lock(&x6500->device_mutex);
|
|
|
if (!jtag_reset(jp)) {
|
|
if (!jtag_reset(jp)) {
|