summaryrefslogtreecommitdiff
path: root/util/mts_util_lora2_reset.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/mts_util_lora2_reset.c')
-rw-r--r--util/mts_util_lora2_reset.c364
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;
+}
+