+/*
+ * Check the necessity for FPGA bitstream upload, because another upload
+ * would take some 600ms which is undesirable after program startup. Try
+ * to access some FPGA registers and check the values' plausibility. The
+ * check should fail on the safe side, request another upload when in
+ * doubt. A positive response (the request to continue operation with the
+ * currently active bitstream) should be conservative. Accessing multiple
+ * registers is considered cheap compared to the cost of bitstream upload.
+ *
+ * It helps though that both the vendor software and the sigrok driver
+ * use the same bundle of MCU firmware and FPGA bitstream for any of the
+ * supported models. We don't expect to successfully communicate to the
+ * device yet disagree on its protocol. Ideally we would access version
+ * identifying registers for improved robustness, but are not aware of
+ * any. A bitstream reload can always be forced by a power cycle.
+ */
+static int check_fpga_bitstream(const struct sr_dev_inst *sdi)
+{
+ uint8_t init_rsp;
+ int ret;
+ uint16_t run_state;
+ uint8_t pwm_en;
+ size_t read_len;
+ uint8_t buff[sizeof(run_state)];
+ const uint8_t *rdptr;
+
+ sr_dbg("Checking operation of the FPGA bitstream.");
+
+ init_rsp = 0xff;
+ ret = ctrl_in(sdi, CMD_FPGA_INIT, 0x00, 0, &init_rsp, sizeof(init_rsp));
+ if (ret != SR_OK || init_rsp != 0) {
+ sr_dbg("FPGA init query failed, or unexpected response.");
+ return SR_ERR_IO;
+ }
+
+ read_len = sizeof(run_state);
+ ret = ctrl_in(sdi, CMD_FPGA_SPI, REG_RUN, 0, buff, read_len);
+ if (ret != SR_OK) {
+ sr_dbg("FPGA register access failed (run state).");
+ return SR_ERR_IO;
+ }
+ rdptr = buff;
+ run_state = read_u16le_inc(&rdptr);
+ sr_spew("FPGA register: run state 0x%04x.", run_state);
+ if (run_state && (run_state & 0x3) != 0x1) {
+ sr_dbg("Unexpected FPGA register content (run state).");
+ return SR_ERR_DATA;
+ }
+ if (run_state && (run_state & ~0xf) != 0x85e0) {
+ sr_dbg("Unexpected FPGA register content (run state).");
+ return SR_ERR_DATA;
+ }
+
+ read_len = sizeof(pwm_en);
+ ret = ctrl_in(sdi, CMD_FPGA_SPI, REG_PWM_EN, 0, buff, read_len);
+ if (ret != SR_OK) {
+ sr_dbg("FPGA register access failed (PWM enable).");
+ return SR_ERR_IO;
+ }
+ rdptr = buff;
+ pwm_en = read_u8_inc(&rdptr);
+ sr_spew("FPGA register: PWM enable 0x%02x.", pwm_en);
+ if ((pwm_en & 0x3) != 0x0) {
+ sr_dbg("Unexpected FPGA register content (PWM enable).");
+ return SR_ERR_DATA;
+ }
+
+ sr_info("Could re-use current FPGA bitstream. No upload required.");
+ return SR_OK;
+}
+