ltc1427.c (7835B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * BCM56xx I2C Device Driver for Linear Technology 1427-50 DAC. 8 * The LTC1427 DAC is used to control voltage outputs on various 9 * SDK baseboards. See the LTC-1427-50 datasheet for more info. 10 */ 11 #include <sal/types.h> 12 #include <soc/debug.h> 13 #include <soc/drv.h> 14 #include <soc/error.h> 15 #include <soc/i2c.h> 16 #include <sal/core/libc.h> 17 #include <shared/bsl.h> 18 #include <soc/util.h> 19 20 #ifdef COMPILER_HAS_DOUBLE 21 #define I2C_DATA_T double 22 #define I2C_DATA_F "f" 23 #else 24 #define I2C_DATA_T int 25 #define I2C_DATA_F "d" 26 #endif 27 28 /* Calibration table in effect */ 29 static dac_calibrate_t* dac_params; 30 static int dac_param_len; 31 32 STATIC int 33 ltc1427_read(int unit, int devno, 34 uint16 addr, uint8* data, uint32* len) 35 { 36 COMPILER_REFERENCE(unit); 37 COMPILER_REFERENCE(devno); 38 COMPILER_REFERENCE(addr); 39 COMPILER_REFERENCE(data); 40 COMPILER_REFERENCE(len); 41 42 return SOC_E_NONE; 43 } 44 45 STATIC int 46 ltc1427_write(int unit, int devno, 47 uint16 addr, uint8* data, uint32 len) 48 { 49 int rv = SOC_E_NONE; 50 uint16 dw = 0; 51 52 if(!data || (len <=0)) 53 return SOC_E_PARAM; 54 55 /* Convert two bytes into single 16bit value */ 56 dw = data[0]; 57 dw <<= 8; 58 dw |= data[1]; 59 60 dw = soc_ntohs(dw); 61 dw &= ~0x8000; /* Make sure we never shut down DAC */ 62 rv = soc_i2c_write_word(unit, soc_i2c_addr(unit, devno), dw); 63 64 soc_i2c_device(unit, devno)->tbyte +=2; 65 return rv; 66 } 67 68 /* 69 * NOTE NOTE NOTE: 70 * All tables (dac_calibrate_t) passed to the ioctl() have size > 1 71 * and the index is always within this range. 72 */ 73 74 #define LTC1427_SET_SELECT_MIN 0 75 #define LTC1427_SET_SELECT_MAX 1 76 #define LTC1427_SET_SELECT_MID 2 77 78 STATIC int 79 ltc1427_setmin_max(int unit, int devno, int set_sel, int idx) 80 { 81 short data; 82 int rv; 83 84 /* set the default voltage */ 85 switch (set_sel) { 86 case LTC1427_SET_SELECT_MAX: 87 data = dac_params[idx].dac_max_hwval; 88 break; 89 case LTC1427_SET_SELECT_MID: 90 data = dac_params[idx].dac_mid_hwval; 91 break; 92 case LTC1427_SET_SELECT_MIN: 93 data = dac_params[idx].dac_min_hwval; 94 break; 95 default: 96 return SOC_E_INTERNAL; 97 } 98 rv = ltc1427_write(unit, devno, 0, (uint8*)&data, sizeof(short)); 99 100 if (SOC_SUCCESS(rv)) { 101 /* Keep last value since DAC is write-only device */ 102 dac_params[idx].dac_last_val = data; 103 } 104 return rv; 105 } 106 107 #define LTC1427_SETMAX(unit,devno, idx) \ 108 ltc1427_setmin_max(unit, devno, LTC1427_SET_SELECT_MAX, idx) 109 #define LTC1427_SETMIN(unit,devno, idx) \ 110 ltc1427_setmin_max(unit, devno, LTC1427_SET_SELECT_MIN, idx) 111 #define LTC1427_SETMID(unit,devno, idx) \ 112 ltc1427_setmin_max(unit, devno, LTC1427_SET_SELECT_MID, idx) 113 114 STATIC int 115 ltc1427_ioctl(int unit, int devno, 116 int opcode, void* data, int len) 117 { 118 int rv = SOC_E_NONE; 119 I2C_DATA_T fval,tmp; 120 uint16 dac; 121 dac_calibrate_t* params = NULL; 122 123 /* length field is actually used as an index into the dac_params table*/ 124 if( !data || ( (dac_params != NULL) && (len > dac_param_len))) 125 return SOC_E_PARAM; 126 127 switch ( opcode ){ 128 129 /* Upload calibration table */ 130 case I2C_DAC_IOC_SET_CALTAB: 131 params = (dac_calibrate_t*)data; 132 dac_params = params; 133 dac_param_len = len; 134 break; 135 136 case I2C_DAC_IOC_SETDAC_MIN: 137 /* Set MIN voltage */ 138 rv = LTC1427_SETMIN(unit, devno, len); 139 break; 140 141 case I2C_DAC_IOC_SETDAC_MAX: 142 /* Set MAX voltage */ 143 rv = LTC1427_SETMAX(unit, devno, len); 144 break; 145 146 case I2C_DAC_IOC_SETDAC_MID: 147 /* Set mid-range voltage */ 148 rv = LTC1427_SETMID(unit, devno, len); 149 break; 150 151 case I2C_DAC_IOC_CALIBRATE_MAX: 152 /* Set MAX output value (from ADC) */ 153 fval = *((I2C_DATA_T*)data); 154 if (dac_params) 155 dac_params[len].max = fval; 156 break; 157 158 case I2C_DAC_IOC_CALIBRATE_MIN: 159 /* Set MIN output value (from ADC) */ 160 fval = *((I2C_DATA_T*)data); 161 if (dac_params) 162 dac_params[len].min = fval; 163 break; 164 165 case I2C_DAC_IOC_CALIBRATE_STEP: 166 /* Calibrate stepsize */ 167 168 if (dac_params) { 169 dac_params[len].step = 170 (dac_params[len].use_max ? -1 : 1) * 171 (dac_params[len].max - dac_params[len].min) / 172 (dac_params[len].dac_max_hwval - dac_params[len].dac_min_hwval); 173 LOG_VERBOSE(BSL_LS_SOC_COMMON, 174 (BSL_META_U(unit, 175 "unit %d i2c %s: LTC1427 calibration on function %s:" 176 "(max=%"I2C_DATA_F",min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"), 177 unit, soc_i2c_devname(unit,devno), 178 dac_params[len].name, 179 dac_params[len].max, 180 dac_params[len].min, 181 dac_params[len].step)); 182 } 183 break; 184 185 case I2C_DAC_IOC_SET_VOUT: 186 /* Set output voltage */ 187 fval = *((I2C_DATA_T*)data); 188 if (dac_params) { 189 if ((fval < dac_params[len].min)||(fval > dac_params[len].max)){ 190 LOG_VERBOSE(BSL_LS_SOC_COMMON, 191 (BSL_META_U(unit, 192 "unit %d i2c %s: calibration/range error :" 193 "requested=%"I2C_DATA_F" (max=%"I2C_DATA_F")," 194 "min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"), 195 unit, soc_i2c_devname(unit,devno), 196 fval, dac_params[len].max, 197 dac_params[len].min, 198 dac_params[len].step)); 199 return SOC_E_PARAM; 200 } 201 /* 202 * Core (A,B,PHY) : DACVAL = VMax - VReq / Step 203 * TurboRef: DACVAL = VReq - VMin / Step 204 */ 205 if(dac_params[len].use_max) 206 tmp = ((dac_params[len].max - fval) / dac_params[len].step); 207 else 208 tmp = ((fval - dac_params[len].min) / dac_params[len].step); 209 dac = (uint16)tmp; 210 211 dac &= LTC1427_VALID_BITS; /* Clear bits to make 10bit value */ 212 213 /* Show what we are doing, for now ... */ 214 LOG_VERBOSE(BSL_LS_SOC_COMMON, 215 (BSL_META_U(unit, 216 "unit %d i2c %s: Set V_%s:" 217 "request=%"I2C_DATA_F" dac=0x%x (max=%"I2C_DATA_F"," 218 "min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"), 219 unit, soc_i2c_devname(unit, devno), 220 dac_params[len].name, 221 fval, 222 dac, 223 dac_params[len].max, 224 dac_params[len].min, 225 dac_params[len].step)); 226 rv = ltc1427_write(unit, devno, 0, (uint8*)&dac, sizeof(short)); 227 /* Keep last value since DAC is write-only device */ 228 dac_params[len].dac_last_val = dac; 229 } 230 break; 231 232 default: 233 LOG_VERBOSE(BSL_LS_SOC_COMMON, 234 (BSL_META_U(unit, 235 "unit %d i2c %s: ltc1427_ioctl: invalid opcode (%d)\n"), 236 unit, soc_i2c_devname(unit,devno), 237 opcode)); 238 break; 239 } 240 241 return rv; 242 } 243 244 STATIC int 245 ltc1427_init(int unit, int devno, 246 void* data, int len) 247 { 248 dac_params = NULL; 249 250 soc_i2c_devdesc_set(unit, devno, "Linear Technology LTC1427 DAC"); 251 252 return SOC_E_NONE; 253 } 254 255 /* LTC1427 Clock Chip Driver callout */ 256 i2c_driver_t _soc_i2c_ltc1427_driver = { 257 0x0, 0x0, /* System assigned bytes */ 258 LTC1427_DEVICE_TYPE, 259 ltc1427_read, 260 ltc1427_write, 261 ltc1427_ioctl, 262 ltc1427_init, 263 NULL, 264 };