diff options
Diffstat (limited to 'util/mts_util_lora2_reset.c')
-rw-r--r-- | util/mts_util_lora2_reset.c | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/util/mts_util_lora2_reset.c b/util/mts_util_lora2_reset.c new file mode 100644 index 0000000..9ec1607 --- /dev/null +++ b/util/mts_util_lora2_reset.c @@ -0,0 +1,364 @@ +/* + Lora 2.1 FPGA and GPS reset utility +*/ + + +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> + + +/* I2C I/O expander specification (BSP) */ +#define I2C_DEVICE "/dev/i2c-0" +#define I2CADDR_PORTEXPANDER 0x20 +#define I2CADDR_EXT_PORTEXPANDER 0x21 + +#define PORTEXPANDER_INPUT_PORT0_REG 0x00 +#define PORTEXPANDER_INPUT_PORT1_REG 0x01 +#define PORTEXPANDER_OUTPUT_PORT0_REG 0x02 +#define PORTEXPANDER_OUTPUT_PORT1_REG 0x03 +#define PORTEXPANDER_CONFIG_PORT0_REG 0x06 +#define PORTEXPANDER_CONFIG_PORT1_REG 0x07 + +#define FPGA_nCE_PORT 0 +#define FPGA_nCONFIG_PORT 1 +#define FPGA_GPS_RESET_PORT 3 +#define FPGA_CONF_DONE_PORT 5 +#define FPGA_EXT_CONF_DONE_PORT 6 + +#define CPU_EPCS_EN_PORT 0 +#define EXT_EPCS_EN_PORT 1 + +#define MAX_FPGA_LOADING_TIMER 10 + +i/* Initial value of the port expander + I/O states (read or read/write). */ +int port_expander_val0 = -1; +int global_i2c_fd = -1; + +int i2c_open( uint8_t i21c_addr ) +{ + global_i2c_fd = open(I2C_DEVICE, O_RDWR); + if( ioctl( global_i2c_fd, I2C_SLAVE, i21c_addr ) < 0 ) + { + fprintf(stderr,"ERROR: Failed to acquire bus access and/or talk to slave - %s\n", strerror(errno) ); + close(global_i2c_fd); + return -1; + } + return 0; +} + +void i2c_close( void ) +{ + if(global_i2c_fd != -1) + close(global_i2c_fd); + global_i2c_fd = 1; +} + +void i2c_read( uint8_t i21c_addr, uint8_t reg_addr, uint8_t *bval ) +{ + struct i2c_msg msg[2]; + struct i2c_rdwr_ioctl_data b; + uint8_t *inbuf, outbuf; + + outbuf = reg_addr; + msg[0].addr = i21c_addr; + msg[0].flags= 0; + msg[0].len = sizeof(outbuf); + msg[0].buf = &outbuf; + + inbuf = bval; + msg[1].addr = i21c_addr; + msg[1].flags = I2C_M_RD; + msg[1].len = sizeof(*inbuf); + msg[1].buf = inbuf; + + b.msgs = msg; + b.nmsgs = 2; + + if( ioctl(global_i2c_fd, I2C_RDWR, &b) < 0 ) + { + fprintf(stderr,"ERROR: Read from I2C Device failed (%d, 0x%02x, 0x%02x) - %s", global_i2c_fd, i21c_addr, reg_addr, strerror(errno) ); + } +} + +void i2c_write( uint8_t i21c_addr, uint8_t reg_addr, uint8_t bval ) +{ + unsigned char buff[2]; + struct i2c_rdwr_ioctl_data b; + struct i2c_msg msg[1]; + + buff[0] = reg_addr; + buff[1] = bval; + + msg[0].addr = i21c_addr; + msg[0].flags = 0; + msg[0].len = sizeof(buff); + msg[0].buf = buff; + + b.msgs = msg; + b.nmsgs = 1; + + if( ioctl(global_i2c_fd, I2C_RDWR, &b) < 0 ) + { + fprintf(stderr,"ERROR: Write to I2C Device failed (%d, 0x%02x, 0x%02x) - %s", global_i2c_fd, i21c_addr, reg_addr, strerror(errno) ); + return; + } + +} + +void usage () +{ + fprintf(stderr, "LoRa Reset utility:\n" ); + fprintf(stderr, " -h : This help\n" ); + fprintf(stderr, " -b : Select board [0,1]\n" ); + fprintf(stderr, " -g : GPS reset\n"); + fprintf(stderr, " -s : Sleep time [0-99999] -- default is 1 second\n"); + fprintf(stderr, " -f : FPGA reset\n" ); + fprintf(stderr, "Either -f or -g or both is required\n" ); +} + +int main( int argc, char ** argv ) +{ + int i, err; + uint8_t val = 0; + uint8_t opt_stime = 1; + uint8_t opt_reset_fpga = 0, opt_gps_reset = 0; + uint8_t board = 0, i2c_expander_addr = I2CADDR_PORTEXPANDER, conf_done_port = FPGA_CONF_DONE_PORT, input_port_reg = PORTEXPANDER_INPUT_PORT0_REG; + int timeout = 0; + + if( argc < 2 ) + { + usage( ); + return EXIT_FAILURE; + } + + /* Parse command line options */ + while( (i = getopt( argc, argv, "b:fghs:" )) != -1 ) + { + switch( i ) + { + case 'g': + opt_gps_reset = 1; + break; + case 'h': + usage( ); + return EXIT_SUCCESS; + break; + case 's': + opt_stime = atoi(optarg); + break; + case 'f': + opt_reset_fpga = 1; + break; + case 'b': + board = atoi(optarg); + fprintf(stderr, "Board %d\n", board ); + break; + + default: + fprintf(stderr, "ERROR: argument parsing options\n" ); + usage( ); + return EXIT_FAILURE; + } + } + + if (!(opt_reset_fpga || opt_gps_reset)) { + fprintf(stderr,"Nothing to do!"); + exit(0); + } + + switch(board) + { + case 0: + i2c_expander_addr = I2CADDR_PORTEXPANDER; + conf_done_port = FPGA_CONF_DONE_PORT; + input_port_reg = PORTEXPANDER_INPUT_PORT0_REG; + break; + case 1: + i2c_expander_addr = I2CADDR_EXT_PORTEXPANDER; + conf_done_port = FPGA_EXT_CONF_DONE_PORT; + input_port_reg = PORTEXPANDER_INPUT_PORT1_REG; + break; + default: + fprintf(stderr, "ERRROR: no board %d\n", board ); + return EXIT_FAILURE; + } + + /* Open the I2C port expander */ + fprintf(stderr, "Opening the I2C Port expander\n" ); + err = i2c_open( I2CADDR_PORTEXPANDER ); + if ( err != 0 ) + { + fprintf(stderr, "ERRROR: failed to open I2C device (err=%i)\n", err ); + return EXIT_FAILURE; + } + + /* Configuration of the I2C port expander */ + i2c_read( I2CADDR_PORTEXPANDER, PORTEXPANDER_CONFIG_PORT0_REG, (uint8_t *)&port_expander_val0 ); + fprintf(stderr, "I2C expander Port 0 config initial state: register: 0x%02x\n", val ); + val = port_expander_val0; + if (opt_reset_fpga) { + val &= ~(1 << FPGA_nCE_PORT); /* CE_PORT as output */ + val &= ~(1 << FPGA_nCONFIG_PORT); /* CONFIG_PORT as output */ + val |= (1 << FPGA_CONF_DONE_PORT); /* CONFIG_DONE as input */ + } + if (opt_gps_reset) + val &= ~(1<<FPGA_GPS_RESET_PORT); /* GPS Reset Port as input */ + + fprintf(stderr, "I2C expander Port 0 config register: 0x%02x\n", val ); + i2c_write( I2CADDR_PORTEXPANDER, PORTEXPANDER_CONFIG_PORT0_REG, val ); + + /* Set port CPU_EPCS_EN and EXT_EPCS_EN as an OUTPUT */ + i2c_read( I2CADDR_PORTEXPANDER, PORTEXPANDER_CONFIG_PORT1_REG, &val ); + val &= ~(1 << CPU_EPCS_EN_PORT); /* CPU_EPCS_EN_PORT as output */ + val &= ~(1 << EXT_EPCS_EN_PORT); /* EXT_EPCS_EN_PORT as output */ + val |= (1 << FPGA_EXT_CONF_DONE_PORT); /* CONFIG_DONE as input */ + i2c_write( I2CADDR_PORTEXPANDER, PORTEXPANDER_CONFIG_PORT1_REG, val ); + i2c_read( I2CADDR_PORTEXPANDER, PORTEXPANDER_CONFIG_PORT1_REG, &val ); + fprintf(stderr, "I2C expander Port 1 config register: 0x%02x\n", val ); + /* Set port CPU_EPCS_EN or EXT_EPCS_EN output level to 1 */ + i2c_read( I2CADDR_PORTEXPANDER, PORTEXPANDER_OUTPUT_PORT1_REG, &val ); + val |= 0x03; + i2c_write( I2CADDR_PORTEXPANDER, PORTEXPANDER_OUTPUT_PORT1_REG, val ); + i2c_read( I2CADDR_PORTEXPANDER, PORTEXPANDER_OUTPUT_PORT1_REG, &val); + fprintf(stderr, "I2C expander Port 1 output level: 0x%02x\n", val ); + + + if( board == 1) + { + /* Close the I2C port expander */ + i2c_close(); + + /* Open the I2C driver */ + fprintf(stderr, "Opening the I2C External Port expander\n" ); + err = i2c_open( I2CADDR_EXT_PORTEXPANDER ); + if ( err != 0 ) + { + fprintf(stderr, "ERRROR: failed to open I2C device (err=%i)\n", err ); + return EXIT_FAILURE; + } + } + + if( opt_gps_reset ) + { + /* GPS RESET PORT HIGH */ + i2c_read( i2c_expander_addr, PORTEXPANDER_CONFIG_PORT0_REG, &val ); + fprintf(stderr, "GPS CONFIG_PORT HIGH\n" ); + val |= (1 << FPGA_GPS_RESET_PORT); + i2c_write( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, val ); + } + + if(opt_reset_fpga) + { + /* Reboot procedure of the FPGA */ + /* nCE LOW */ + i2c_read( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, &val ); + fprintf(stderr, "I2C nCE LOW\n" ); + val &= ~(1 << FPGA_nCE_PORT); + i2c_write( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, val ); + } + sleep( opt_stime ); + + if( opt_gps_reset ) + { + /* GPS RESET PORT LOW */ + i2c_read( i2c_expander_addr, PORTEXPANDER_CONFIG_PORT0_REG, &val ); + fprintf(stderr, "GPS CONFIG_PORT LOW\n" ); + val &= ~(1 << FPGA_GPS_RESET_PORT); + i2c_write( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, val ); + } + + if(opt_reset_fpga) + { + /* FPGA_PORT LOW */ + i2c_read( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, &val ); + fprintf(stderr, "I2C CONFIG_PORT LOW\n" ); + val &= ~(1 << FPGA_nCONFIG_PORT); + i2c_write( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, val ); + } + + sleep( opt_stime ); + + if( opt_gps_reset ) + { + /* GPS RESET PORT HIGH */ + i2c_read( i2c_expander_addr, PORTEXPANDER_CONFIG_PORT0_REG, &val ); + fprintf(stderr, "GPS CONFIG_PORT HIGH\n" ); + val |= (1 << FPGA_GPS_RESET_PORT); + i2c_write( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, val ); + } + + if(opt_reset_fpga) + { + /* FPGA_PORT HIGH */ + i2c_read( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, &val ); + fprintf(stderr, "I2C CONFIG_PORT HIGH\n" ); + val |= (1 << FPGA_nCONFIG_PORT); + i2c_write( i2c_expander_addr, PORTEXPANDER_OUTPUT_PORT0_REG, val ); + } + + + if(board == 1) + { + /* Close the external I2C port expander */ + i2c_close(); + + /* Open the I2C driver */ + fprintf(stderr, "Opening the I2C Port expander\n" ); + err = i2c_open( I2CADDR_PORTEXPANDER ); + if ( err != 0 ) + { + fprintf(stderr, "ERRROR: failed to open I2C device (err=%i)\n", err ); + return EXIT_FAILURE; + } + } + + if(opt_reset_fpga) { + /* WAIT for CONFIG_DONE high on the FPGA */ + timeout = 0; + fprintf(stderr,"input_port_reg %d conf_done_port %d\n",input_port_reg, conf_done_port); + do + { + i2c_read( I2CADDR_PORTEXPANDER, input_port_reg, &val); + sleep( opt_stime ); + timeout++; + } while( !(val & (1 << conf_done_port)) && (timeout <= MAX_FPGA_LOADING_TIMER) ); + if( !(val & (1 << conf_done_port) ) ) + { + fprintf(stderr, "FATAL ERROR: Reboot of the FPGA in failure val %d\n", val ); + } + else + { + fprintf(stderr, "I2C CONFIG_DONE HIGH\n" ); + } + } + + /* Close the I2C driver */ + i2c_close(); + + /* Set the port expander back to its initial state */ + fprintf(stderr, "Opening the I2C Port expander\n" ); + err = i2c_open( I2CADDR_PORTEXPANDER ); + if ( err != 0 ) + { + fprintf(stderr, "ERRROR: failed to open I2C device (err=%i)\n", err ); + return EXIT_FAILURE; + } + fprintf(stderr, "I2C expander Port 0 config register: 0x%02x\n", port_expander_val0 ); + i2c_write( I2CADDR_PORTEXPANDER, PORTEXPANDER_CONFIG_PORT0_REG, port_expander_val0 ); + i2c_close(); + + return 0; +} + |