#ifndef ZF_LOG_LEVEL #define ZF_LOG_LEVEL ZF_LOG_VERBOSE #endif #define ZF_LOG_DEF_SRCLOC ZF_LOG_SRCLOC_LONG #define ZF_LOG_TAG "FPGA" #include "zf_log/zf_log.h" #include #include #include "caribou_fpga.h" //-------------------------------------------------------------- // Static Definitions //-------------------------------------------------------------- #define IOC_MOD_VER 0 #define IOC_SYS_CTRL_SYS_VERSION 1 #define IOC_SYS_CTRL_MANU_ID 2 #define IOC_SYS_CTRL_SYS_ERR_STAT 3 #define IOC_SYS_CTRL_SYS_SOFT_RST 4 #define IOC_SYS_CTRL_DEBUG_MODES 5 #define IOC_SYS_CTRL_TX_SAMPLE_GAP 6 #define IOC_SYS_CTRL_SOFT_SYNC 7 #define IOC_IO_CTRL_MODE 1 #define IOC_IO_CTRL_DIG_PIN 2 #define IOC_IO_CTRL_PMOD_DIR 3 #define IOC_IO_CTRL_PMOD_VAL 4 #define IOC_IO_CTRL_RF_PIN 5 #define IOC_IO_CTRL_MXR_FM_PS 6 #define IOC_IO_CTRL_MXR_FM_DATA 7 #define IOC_SMI_CTRL_FIFO_STATUS 1 #define IOC_SMI_CHANNEL_SELECT 2 #define IOC_SMI_CTRL_DIR_SELECT 3 //-------------------------------------------------------------- // Internal Data-Types //-------------------------------------------------------------- #pragma pack(1) typedef enum { caribou_fpga_rw_read = 0, caribou_fpga_rw_write = 1, } caribou_fpga_rw_en; typedef enum { caribou_fpga_mid_sys_ctrl = 0, caribou_fpga_mid_io_ctrl = 1, caribou_fpga_mid_smi_ctrl = 2, caribou_fpga_mid_res = 3, } caribou_fpga_mid_en; typedef struct { uint8_t ioc : 5; caribou_fpga_mid_en mid : 2; caribou_fpga_rw_en rw : 1; // MSB } caribou_fpga_opcode_st; #pragma pack() #define CARIBOU_FPGA_CHECK_DEV(d,f) \ { \ if ((d)==NULL) { ZF_LOGE("%s: dev is NULL", (f)); return -1;} \ if (!(d)->initialized) {ZF_LOGE("%s: dev not initialized", (f)); return -1;} \ } #define CARIBOU_FPGA_CHECK_PTR_NOT_NULL(p,f,n) {if ((p)==NULL) {ZF_LOGE("%s: %s is NULL",(f),(n)); return -1;}} //=================================================================== void caribou_fpga_interrupt_handler (int event, int level, uint32_t tick, void *data) { //int i; //caribou_fpga_st* dev = (caribou_fpga_st*)data; /*for (i=0; iio_spi, dev->io_spi_handle, tx_buf, rx_buf, 2, io_utils_spi_read_write); if (ret<0) { ZF_LOGE("spi transfer failed (%d)", ret); return -1; } // on success return 0 (the number of transmitted bytes are same as needed), // otherwise '1' (warning / error) *data = rx_buf[1]; return !(ret == sizeof(rx_buf)); } //-------------------------------------------------------------- int caribou_fpga_init(caribou_fpga_st* dev, io_utils_spi_st* io_spi) { if (dev == NULL) { ZF_LOGE("dev is NULL"); return -1; } dev->io_spi = io_spi; ZF_LOGD("configuring reset and irq pins"); // Configure GPIO pins io_utils_setup_gpio(dev->reset_pin, io_utils_dir_output, io_utils_pull_up); io_utils_setup_gpio(dev->soft_reset_pin, io_utils_dir_output, io_utils_pull_up); // set to known state io_utils_write_gpio(dev->soft_reset_pin, 1); ZF_LOGD("Initializing io_utils_spi"); io_utils_hard_spi_st hard_dev_fpga = { .spi_dev_id = dev->spi_dev, .spi_dev_channel = dev->spi_channel, }; dev->io_spi_handle = io_utils_spi_add_chip(dev->io_spi, dev->cs_pin, 1000000, 0, 0, io_utils_spi_chip_type_fpga_comm, &hard_dev_fpga); // Init FPGA programming if (caribou_prog_init(&dev->prog_dev, dev->io_spi) < 0) { ZF_LOGE("ice40 programmer init failed"); return -1; } dev->initialized = 1; return 0; } //-------------------------------------------------------------- int caribou_fpga_get_status(caribou_fpga_st* dev, caribou_fpga_status_en *stat) { int retries = 3; int inner_stat = caribou_fpga_status_not_programmed; while (retries-- && inner_stat != caribou_fpga_status_operational) { caribou_fpga_get_versions (dev, NULL); if (dev->versions.sys_manu_id != CARIBOU_SDR_MANU_CODE) { inner_stat = caribou_fpga_status_not_programmed; //caribou_fpga_print_versions (dev); caribou_fpga_soft_reset(dev); io_utils_usleep(20000); } else { inner_stat = caribou_fpga_status_operational; } } dev->status = inner_stat; if (stat) *stat = dev->status; return 0; } //-------------------------------------------------------------- int caribou_fpga_program_to_fpga(caribou_fpga_st* dev, unsigned char *buffer, size_t len, bool force_prog) { int prog_retries = 3; caribou_fpga_get_status(dev, NULL); if (dev->status == caribou_fpga_status_not_programmed || force_prog) { if (buffer == NULL || len == 0) { ZF_LOGE("buffer should be not NULL and len > 0"); return -1; } while (prog_retries--) { if (caribou_prog_configure_from_buffer(&dev->prog_dev, buffer, len) != 0) { continue; } //caribou_fpga_soft_reset(dev); io_utils_usleep(100000); caribou_fpga_get_status(dev, NULL); if (dev->status == caribou_fpga_status_operational) { break; } } if (prog_retries == 0) { ZF_LOGE("Programming failed"); return -1; } } else { ZF_LOGI("FPGA already operational - not programming (use 'force_prog=true' to force update)"); } return 0; } //-------------------------------------------------------------- int caribou_fpga_program_to_fpga_from_file(caribou_fpga_st* dev, char *filename, bool force_prog) { caribou_fpga_get_status(dev, NULL); if (dev->status == caribou_fpga_status_not_programmed || force_prog) { if (caribou_prog_configure(&dev->prog_dev, filename) < 0) { ZF_LOGE("Programming failed"); return -1; } caribou_fpga_soft_reset(dev); io_utils_usleep(100000); caribou_fpga_get_status(dev, NULL); if (dev->status == caribou_fpga_status_not_programmed) { ZF_LOGE("Programming failed"); return -1; } } else { ZF_LOGI("FPGA already operational - not programming (use 'force_prog=true' to force update)"); } return 0; } //-------------------------------------------------------------- int caribou_fpga_close(caribou_fpga_st* dev) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_close"); dev->initialized = 0; io_utils_spi_remove_chip(dev->io_spi, dev->io_spi_handle); return caribou_prog_release(&dev->prog_dev); } //-------------------------------------------------------------- int caribou_fpga_soft_reset(caribou_fpga_st* dev) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_soft_reset"); io_utils_write_gpio_with_wait(dev->soft_reset_pin, 0, 1000); io_utils_usleep(1000); io_utils_write_gpio_with_wait(dev->soft_reset_pin, 1, 1000); io_utils_usleep(20000); return 0; } //-------------------------------------------------------------- int caribou_fpga_hard_reset(caribou_fpga_st* dev) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_hard_reset (disposing firmware)"); io_utils_write_gpio_with_wait(dev->reset_pin, 0, 1000); io_utils_write_gpio_with_wait(dev->reset_pin, 1, 1000); return 0; } //-------------------------------------------------------------- int caribou_fpga_hard_reset_keep(caribou_fpga_st* dev, bool reset) { if (reset) { io_utils_write_gpio_with_wait(dev->reset_pin, 0, 1000); } else { io_utils_write_gpio_with_wait(dev->reset_pin, 1, 1000); } return 0; } //-------------------------------------------------------------- // System Controller void caribou_fpga_print_versions (caribou_fpga_st* dev) { printf("FPGA Versions:\n"); printf(" System Version: %02X\n", dev->versions.sys_ver); printf(" Manu. ID: %02X\n", dev->versions.sys_manu_id); printf(" Sys. Ctrl Version: %02X\n", dev->versions.sys_ctrl_mod_ver); printf(" IO Ctrl Version: %02X\n", dev->versions.io_ctrl_mod_ver); printf(" SMI Ctrl Version: %02X\n", dev->versions.smi_ctrl_mod_ver); } //-------------------------------------------------------------- int caribou_fpga_get_versions (caribou_fpga_st* dev, caribou_fpga_versions_st* vers) { caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_sys_ctrl, }; uint8_t *poc = (uint8_t*)&oc; CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_versions"); oc.ioc = IOC_SYS_CTRL_SYS_VERSION; caribou_fpga_spi_transfer (dev, poc, &dev->versions.sys_ver); oc.ioc = IOC_SYS_CTRL_MANU_ID; caribou_fpga_spi_transfer (dev, poc, &dev->versions.sys_manu_id); oc.ioc = IOC_MOD_VER; oc.mid = caribou_fpga_mid_sys_ctrl; caribou_fpga_spi_transfer (dev, poc, &dev->versions.sys_ctrl_mod_ver); oc.mid = caribou_fpga_mid_io_ctrl; caribou_fpga_spi_transfer (dev, poc, &dev->versions.io_ctrl_mod_ver); oc.mid = caribou_fpga_mid_smi_ctrl; caribou_fpga_spi_transfer (dev, poc, &dev->versions.smi_ctrl_mod_ver); //caribou_fpga_print_versions (dev); if (vers) { memcpy (vers, &dev->versions, sizeof(caribou_fpga_versions_st)); } return 0; } //-------------------------------------------------------------- static char caribou_fpga_mode_names[][64] = { "Low Power (0)", "RX / TX bypass (1)", "RX lowpass (up-conversion) (2)", "RX hipass (down-conversion) (3)", "TX lowpass (down-conversion) (4)", "RX hipass (up-conversion) (5)", }; char* caribou_fpga_get_mode_name (caribou_fpga_io_ctrl_rfm_en mode) { if (mode >= caribou_fpga_io_ctrl_rfm_low_power && mode <= caribou_fpga_io_ctrl_rfm_tx_hipass) return caribou_fpga_mode_names[mode]; return NULL; } //-------------------------------------------------------------- int caribou_fpga_set_debug_modes (caribou_fpga_st* dev, bool dbg_fifo_push, bool dbg_fifo_pull, bool dbg_smi) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_debug_modes"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_sys_ctrl, .ioc = IOC_SYS_CTRL_DEBUG_MODES }; uint8_t mode = ((dbg_fifo_push & 0x1) << 0) | ((dbg_fifo_pull & 0x1) << 1) | ((dbg_smi & 0x1) << 2 ); return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &mode); } //-------------------------------------------------------------- int caribou_fpga_get_errors (caribou_fpga_st* dev, uint8_t *err_map) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_errors"); CARIBOU_FPGA_CHECK_PTR_NOT_NULL(err_map,"caribou_fpga_get_errors","err_map"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_sys_ctrl, .ioc = IOC_SYS_CTRL_SYS_ERR_STAT }; if (err_map) { *err_map = 0; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), err_map); } return -1; } //-------------------------------------------------------------- int caribou_fpga_set_sys_ctrl_tx_sample_gap (caribou_fpga_st* dev, uint8_t gap) { uint8_t actual_val = 0; uint8_t actual_gap = 0; CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_sys_ctrl_tx_sample_gap"); // read before write caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_sys_ctrl, .ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP, }; int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_val); if (ret != 0) return -1; actual_gap = actual_val & 0xF; actual_val &= 0xF0; if (gap != actual_gap) { // only if change is needed oc.rw = caribou_fpga_rw_write; actual_val |= (gap & 0xF); return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_val); } return 0; } //-------------------------------------------------------------- int caribou_fpga_get_sys_ctrl_tx_sample_gap (caribou_fpga_st* dev, uint8_t *gap) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_sys_ctrl_tx_sample_gap"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_sys_ctrl, .ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP }; uint8_t actual_gap = 0; int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_gap); if (gap) *gap = actual_gap & 0xF; return ret; } //-------------------------------------------------------------- int caribou_fpga_set_sys_ctrl_sync_source (caribou_fpga_st* dev, caribou_fpga_sync_source_en rx_09, caribou_fpga_sync_source_en rx_24, caribou_fpga_sync_source_en tx_09, caribou_fpga_sync_source_en tx_24) { uint8_t actual_val = 0; uint8_t temp = 0; CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_sys_ctrl_sync_source"); // read before write caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_sys_ctrl, .ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP, }; int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &actual_val); if (ret != 0) return -1; temp = actual_val & 0xF; uint8_t cur_rx_09 = (actual_val >> 4) & 0x1; uint8_t cur_rx_24 = (actual_val >> 5) & 0x1; uint8_t cur_tx_09 = (actual_val >> 6) & 0x1; uint8_t cur_tx_24 = (actual_val >> 7) & 0x1; if (rx_09 != caribou_fpga_sync_src_no_change) cur_rx_09 = rx_09 & 0x1; if (rx_24 != caribou_fpga_sync_src_no_change) cur_rx_24 = rx_24 & 0x1; if (tx_09 != caribou_fpga_sync_src_no_change) cur_tx_09 = tx_09 & 0x1; if (tx_24 != caribou_fpga_sync_src_no_change) cur_tx_24 = tx_24 & 0x1; temp |= cur_rx_09 << 4; temp |= cur_rx_24 << 5; temp |= cur_tx_09 << 6; temp |= cur_tx_24 << 7; oc.rw = caribou_fpga_rw_write; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &temp); } //-------------------------------------------------------------- int caribou_fpga_get_sys_ctrl_sync_source (caribou_fpga_st* dev, caribou_fpga_sync_source_en *rx_09, caribou_fpga_sync_source_en *rx_24, caribou_fpga_sync_source_en *tx_09, caribou_fpga_sync_source_en *tx_24) { uint8_t temp = 0; CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_sys_ctrl_sync_source"); // read before write caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_sys_ctrl, .ioc = IOC_SYS_CTRL_TX_SAMPLE_GAP, }; int ret = caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &temp); if (ret != 0) return -1; if (rx_09) *rx_09 = (temp >> 4) & 0x1; if (rx_24) *rx_24 = (temp >> 5) & 0x1; if (tx_09) *tx_09 = (temp >> 6) & 0x1; if (tx_24) *tx_24 = (temp >> 7) & 0x1; return 0; } //-------------------------------------------------------------- int caribou_fpga_set_sys_ctrl_soft_sync_value (caribou_fpga_st* dev, uint8_t rx_09, uint8_t rx_24, uint8_t tx_09, uint8_t tx_24) { uint8_t temp = (rx_09 & 0xf) | ((tx_09 & 0xf) << 1) | ((rx_24 & 0xf) << 2) | ((tx_24 & 0xf) << 3); CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_sys_ctrl_soft_sync_value"); // read before write caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_sys_ctrl, .ioc = IOC_SYS_CTRL_SOFT_SYNC, }; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &temp); } //-------------------------------------------------------------- // I/O Controller int caribou_fpga_set_io_ctrl_mode (caribou_fpga_st* dev, uint8_t debug_mode, caribou_fpga_io_ctrl_rfm_en rfm) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_io_ctrl_mode"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_MODE }; uint8_t mode = (debug_mode << 0) | (rfm&0x7)<<2; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &mode); } //-------------------------------------------------------------- int caribou_fpga_get_io_ctrl_mode (caribou_fpga_st* dev, uint8_t* debug_mode, caribou_fpga_io_ctrl_rfm_en* rfm) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_io_ctrl_mode"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_MODE }; uint8_t mode = 0; caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &mode); if (debug_mode) *debug_mode = mode & 0x3; if (rfm) *rfm = (mode >> 2) & 0x7; return 0; } //-------------------------------------------------------------- int caribou_fpga_set_io_ctrl_dig (caribou_fpga_st* dev, int led0, int led1) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_io_ctrl_dig"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_DIG_PIN }; uint8_t pins = led1<<1 | led0<<0; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &pins); } //-------------------------------------------------------------- int caribou_fpga_get_io_ctrl_dig (caribou_fpga_st* dev, int* led0, int* led1, int* btn, int* cfg) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_io_ctrl_dig"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_DIG_PIN }; uint8_t pins = 0; caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &pins); if (led0) *led0 = (pins>>0)&0x01; if (led1) *led1 = (pins>>1)&0x01; if (cfg) *cfg = (pins>>3)&0x0F; if (btn) *btn = (pins>>7)&0x01; return 0; } //-------------------------------------------------------------- int caribou_fpga_set_io_ctrl_pmod_dir (caribou_fpga_st* dev, uint8_t dir) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_io_ctrl_pmod_dir"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_PMOD_DIR }; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &dir); } //-------------------------------------------------------------- int caribou_fpga_get_io_ctrl_pmod_dir (caribou_fpga_st* dev, uint8_t *dir) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_io_ctrl_pmod_dir"); CARIBOU_FPGA_CHECK_PTR_NOT_NULL(dir,"caribou_fpga_get_io_ctrl_pmod_dir","dir"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_PMOD_DIR }; if (dir) { *dir = 0; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), dir); } return -1; } //-------------------------------------------------------------- int caribou_fpga_set_io_ctrl_pmod_val (caribou_fpga_st* dev, uint8_t val) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_io_ctrl_pmod_val"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_PMOD_VAL }; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &val); } //-------------------------------------------------------------- int caribou_fpga_get_io_ctrl_pmod_val (caribou_fpga_st* dev, uint8_t *val) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_io_ctrl_pmod_val"); CARIBOU_FPGA_CHECK_PTR_NOT_NULL(val,"caribou_fpga_get_io_ctrl_pmod_val","val"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_PMOD_VAL }; if (val) { *val = 0; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), val); } return -1; } //-------------------------------------------------------------- int caribou_fpga_set_io_ctrl_rf_state (caribou_fpga_st* dev, caribou_fpga_rf_pin_st *pins) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_io_ctrl_rf_state"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_RF_PIN }; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)pins); } //-------------------------------------------------------------- int caribou_fpga_get_io_ctrl_rf_state (caribou_fpga_st* dev, caribou_fpga_rf_pin_st *pins) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_io_ctrl_rf_state"); CARIBOU_FPGA_CHECK_PTR_NOT_NULL(pins,"caribou_fpga_get_io_ctrl_rf_state","pins"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_io_ctrl, .ioc = IOC_IO_CTRL_RF_PIN }; if (pins) { memset(pins, 0, sizeof(caribou_fpga_rf_pin_st)); return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)pins); } return -1; } //-------------------------------------------------------------- int caribou_fpga_get_smi_ctrl_fifo_status (caribou_fpga_st* dev, caribou_fpga_smi_fifo_status_st *status) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_get_smi_ctrl_fifo_status"); CARIBOU_FPGA_CHECK_PTR_NOT_NULL(status,"caribou_fpga_get_smi_ctrl_fifo_status","status"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_read, .mid = caribou_fpga_mid_smi_ctrl, .ioc = IOC_SMI_CTRL_FIFO_STATUS }; if (status) { memset(status, 0, sizeof(caribou_fpga_smi_fifo_status_st)); return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)status); } return -1; } //-------------------------------------------------------------- int caribou_fpga_set_smi_channel (caribou_fpga_st* dev, caribou_fpga_smi_channel_en channel) { uint8_t val = 0; CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_smi_channel"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_smi_ctrl, .ioc = IOC_SMI_CHANNEL_SELECT }; val = (channel == caribou_fpga_smi_channel_0) ? 0x0 : 0x1; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), &val); } //-------------------------------------------------------------- int caribou_fpga_set_smi_ctrl_data_direction (caribou_fpga_st* dev, uint8_t dir) { CARIBOU_FPGA_CHECK_DEV(dev,"caribou_fpga_set_smi_ctrl_data_direction"); caribou_fpga_opcode_st oc = { .rw = caribou_fpga_rw_write, .mid = caribou_fpga_mid_smi_ctrl, .ioc = IOC_SMI_CTRL_DIR_SELECT }; return caribou_fpga_spi_transfer (dev, (uint8_t*)(&oc), (uint8_t*)&dir); }