/* Lora 2.1 FPGA and GPS reset utility */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* 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 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\n", 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\n", 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!\n"); 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 *)&val ); fprintf(stderr, "I2C expander Port 0 config initial state: register: 0x%02x\n", val ); 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<