/ A1-desk-board-selector.c
A1-desk-board-selector.c
  1  #include <sys/ioctl.h>
  2  #include <errno.h>
  3  #include <string.h>
  4  #include <stdio.h>
  5  #include <stdlib.h>
  6  #include <unistd.h>
  7  #include <linux/i2c.h>
  8  #include <linux/i2c-dev.h>
  9  
 10  #include <stdint.h>
 11  #include <stdbool.h>
 12  #include <fcntl.h>
 13  
 14  #include "miner.h"
 15  
 16  struct pcf8575_ctx {
 17  	uint8_t addr;
 18  	uint8_t p0;
 19  	uint8_t p1;
 20  	int file;
 21  	uint8_t active_board;
 22  	pthread_mutex_t lock;
 23  };
 24  
 25  static struct pcf8575_ctx board_ctx = { 0x27, 0xff, 0xff, -1, .active_board = 255,};
 26  
 27  
 28  #define UNUSED_BITS 0xe0
 29  #define SLEEP_MS_AFTER_CS 0
 30  static bool pcf8575_write(void)
 31  {
 32  	union i2c_smbus_data data;
 33  	data.byte = board_ctx.p1 | UNUSED_BITS;
 34  
 35  	struct i2c_smbus_ioctl_data args;
 36  	__s32 err;
 37  
 38  	args.read_write = I2C_SMBUS_WRITE;
 39  	args.command = board_ctx.p0 | UNUSED_BITS;
 40  	args.size = I2C_SMBUS_BYTE_DATA;
 41  	args.data = &data;
 42  
 43  	err = ioctl(board_ctx.file, I2C_SMBUS, &args);
 44  	if (err == -1) {
 45  		fprintf(stderr,
 46  			"Error: Failed to write: %s\n",
 47  			strerror(errno));
 48  		err = -errno;
 49  	} else {
 50  		applog(LOG_DEBUG, "written: 0x%02x, 0x%02x", board_ctx.p0, board_ctx.p1);
 51  //		usleep(25000);
 52  		cgsleep_ms(SLEEP_MS_AFTER_CS);
 53  	}
 54  	return err == 0;
 55  }
 56  
 57  void lock_board_selector(void)
 58  {
 59  //	applog(LOG_WARNING, "lock_board_selector()");
 60  	mutex_lock(&board_ctx.lock);
 61  }
 62  
 63  void unlock_board_selector(void)
 64  {
 65  //	applog(LOG_WARNING, "unlock_board_selector()");
 66  	mutex_unlock(&board_ctx.lock);
 67  }
 68  
 69  bool a1_board_selector_init(void)
 70  {
 71  	mutex_init(&board_ctx.lock);
 72  	applog(LOG_WARNING, "a1_board_selector_init()");
 73  
 74  	board_ctx.file = open("/dev/i2c-1", O_RDWR);
 75  	if (board_ctx.file < 0) {
 76  		fprintf(stderr,
 77  			"Error: Could not open i2c-1: %s\n",
 78  			board_ctx.addr, strerror(errno));
 79  		return false;
 80  	}
 81  
 82  	if (ioctl(board_ctx.file, I2C_SLAVE, board_ctx.addr) < 0) {
 83  		fprintf(stderr,
 84  			"Error: Could not set address to 0x%02x: %s\n",
 85  			board_ctx.addr, strerror(errno));
 86  		return false;
 87  	}
 88  	return pcf8575_write();
 89  }
 90  
 91  void a1_board_selector_exit(void)
 92  {
 93  	close(board_ctx.file);
 94  	board_ctx.file = -1;
 95  }
 96  
 97  bool a1_board_selector_select_board(uint8_t board)
 98  {
 99  	if (board > 7)
100  		return false;
101  
102  //	applog(LOG_WARNING, "board_selector_select_board(%d)", board);
103  	lock_board_selector();
104  	if (board_ctx.active_board == board)
105  		return true;
106  
107  	board_ctx.active_board = board;
108  	board_ctx.p0 = 1 << board_ctx.active_board;
109  	board_ctx.p1 = 0xff;
110  	bool retval = pcf8575_write();
111  	return retval;
112  }
113  
114  static bool __board_selector_reset(void)
115  {
116  	board_ctx.p1 = ~board_ctx.p0;
117  	if (!pcf8575_write())
118  		return false;
119  	usleep(1000000);
120  	board_ctx.p1 = 0xff;
121  	if (!pcf8575_write())
122  		return false;
123  	usleep(1000000);
124  	return true;
125  }
126  // we assume we are already holding the mutex
127  bool a1_board_selector_reset_board(void)
128  {
129  //	lock_board_selector();
130  	bool retval = __board_selector_reset();
131  //	unlock_board_selector();
132  	return retval;
133  }
134  
135  bool a1_board_selector_reset_all_boards(void)
136  {
137  	lock_board_selector();
138  	board_ctx.p1 = 0;
139  	bool retval = __board_selector_reset();
140  	unlock_board_selector();
141  	return retval;
142  }
143  
144  #if 0
145  int main(void)
146  {
147  	if (init_pcf8575(&board_ctx)) {
148  		if (!pcf8575_write(&g_ctx)) {
149  			fprintf(stderr,
150  				"Error: Failed to write: %s\n",
151  				strerror(errno));
152  		}
153  		a1_board_selector_exit(&g_ctx);
154  	}
155  	return 0;
156  }
157  #endif
158  /////////////////////////////////////////////////////////////////////////////