/ A1-board-selector-CCD.c
A1-board-selector-CCD.c
1 /* 2 * board selector support for TCA9535 used in Bitmine's CoinCraft Desk 3 * 4 * Copyright 2014 Zefir Kurtisi <zefir.kurtisi@gmail.com> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License as published by the Free 8 * Software Foundation; either version 3 of the License, or (at your option) 9 * any later version. See COPYING for more details. 10 */ 11 12 13 #include <sys/ioctl.h> 14 #include <errno.h> 15 #include <string.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <unistd.h> 19 #include <linux/i2c.h> 20 #include <linux/i2c-dev.h> 21 22 #include <stdint.h> 23 #include <stdbool.h> 24 #include <fcntl.h> 25 26 #include "miner.h" 27 28 #include "A1-board-selector.h" 29 #include "i2c-context.h" 30 31 static struct board_selector ccd_selector; 32 33 struct i2c_ctx *U1_tca9535; 34 uint8_t chain_mask = 0xff; 35 uint8_t active_chain = 255; 36 pthread_mutex_t lock; 37 38 39 #define UNUSED_BITS 0xe0 40 41 static void ccd_unlock(void) 42 { 43 mutex_unlock(&lock); 44 } 45 46 static void ccd_exit(void) 47 { 48 if (U1_tca9535 != NULL) 49 U1_tca9535->exit(U1_tca9535); 50 } 51 uint8_t retval = 0; 52 53 extern struct board_selector *ccd_board_selector_init(void) 54 { 55 mutex_init(&lock); 56 U1_tca9535 = i2c_slave_open(I2C_BUS, 0x27); 57 if (U1_tca9535 == NULL) 58 return NULL; 59 bool retval = U1_tca9535->write(U1_tca9535, 0x06, 0xe0) && 60 U1_tca9535->write(U1_tca9535, 0x07, 0xe0) && 61 U1_tca9535->write(U1_tca9535, 0x02, 0x1f) && 62 U1_tca9535->write(U1_tca9535, 0x03, 0x00); 63 if (retval) 64 return &ccd_selector; 65 ccd_exit(); 66 return NULL; 67 } 68 69 static bool ccd_select(uint8_t chain) 70 { 71 if (chain >= CCD_MAX_CHAINS) 72 return false; 73 74 mutex_lock(&lock); 75 if (active_chain == chain) 76 return true; 77 78 active_chain = chain; 79 chain_mask = 1 << active_chain; 80 return U1_tca9535->write(U1_tca9535, 0x02, ~chain_mask); 81 } 82 83 static bool __ccd_board_selector_reset(uint8_t mask) 84 { 85 if (!U1_tca9535->write(U1_tca9535, 0x03, mask)) 86 return false; 87 cgsleep_ms(RESET_LOW_TIME_MS); 88 if (!U1_tca9535->write(U1_tca9535, 0x03, 0x00)) 89 return false; 90 cgsleep_ms(RESET_HI_TIME_MS); 91 return true; 92 } 93 // we assume we are already holding the mutex 94 static bool ccd_reset(void) 95 { 96 return __ccd_board_selector_reset(chain_mask); 97 } 98 99 static bool ccd_reset_all(void) 100 { 101 mutex_lock(&lock); 102 bool retval = __ccd_board_selector_reset(0xff & ~UNUSED_BITS); 103 mutex_unlock(&lock); 104 return retval; 105 } 106 107 108 static struct board_selector ccd_selector = { 109 .select = ccd_select, 110 .release = ccd_unlock, 111 .exit = ccd_exit, 112 .reset = ccd_reset, 113 .reset_all = ccd_reset_all, 114 /* don't have a temp sensor dedicated to chain */ 115 .get_temp = dummy_get_temp, 116 }; 117