ltc388x.c (75159B)
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 * I2C Device Driver for LTC388X an integrated power control IC. 8 * 9 * For new chip with Resistor configurations add new resistor 10 * configuration array [ for ex sense_resistor_config_56960k 11 * for Tomahawk chip] and initalise with the appropriate index 12 * (chip number-G42) in IOCTL opcodes I2C_LTC_IOC_SET_CONFIG and 13 * I2C_LTC_IOC_SET_RCONFIG. 14 */ 15 16 #include <sal/types.h> 17 #include <soc/debug.h> 18 #include <soc/drv.h> 19 #include <soc/error.h> 20 #include <soc/i2c.h> 21 #include <shared/bsl.h> 22 #include <sal/appl/sal.h> 23 24 typedef struct device_data_s { 25 sal_mutex_t lock; /* mutex lock for device operation */ 26 dac_calibrate_t *dac_params; /*dac params for each device channel*/ 27 int dac_param_len; 28 } device_data_t; 29 30 #define DEV_MUTEX(dev) \ 31 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->lock) 32 #define DEV_DAC_PARAMS(dev) \ 33 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->dac_params) 34 #define DEV_DAC_PARAM_LEN(dev) \ 35 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->dac_param_len) 36 #define DEV_CHECK_RETURN(dev) \ 37 { \ 38 if ((dev) == NULL) { \ 39 return SOC_E_INTERNAL; \ 40 } \ 41 } 42 #define DEV_PRIVDATA_CHECK_RETURN(dev) \ 43 { \ 44 DEV_CHECK_RETURN(dev) \ 45 if ((dev)->priv_data == NULL) { \ 46 return SOC_E_INTERNAL; \ 47 } \ 48 } 49 50 /* L16 format conversions */ 51 #define L16_TO_V(val) ((val)*100000/4096/100000) 52 #define V_TO_L16(val) ((val)*4096) 53 #define L16_TO_UV(val) ((val)*100000/4096*10) 54 #define UV_TO_L16(val) ((val)/10*4096/100000) 55 56 /* The ranges are defined in unit of one part per 100000 */ 57 #define FAULT_LIMIT_RANGE 10000 58 #define WARN_LIMIT_RANGE 7500 59 #define MARGIN_RANGE 5000 60 #define POWER_GOOD_ON_RANGE 7000 61 #define POWER_GOOD_OFF_RANGE 8000 62 63 #define MAX_VS_CONFIG 15 64 #define SB2_MAX_VS_CONFIG 6 65 #define AP_MAX_VS_CONFIG 4 66 #define FB5_MAX_VS_CONFIG 5 67 #define HR3_MAX_VS_CONFIG 6 68 #define GH2_MAX_VS_CONFIG 6 69 #define MN_MAX_VS_CONFIG 3 70 #define WH2_MAX_VS_CONFIG 5 71 #define FB5_MAX_VS_CONFIG 5 72 #define HX5_MAX_VS_CONFIG 9 73 74 75 #define L16_RANGE_UPPER(L16, range) ((L16) + (int)(range)*L16/100000) 76 #define L16_RANGE_LOWER(L16, range) ((L16) - (int)(range)*L16/100000) 77 78 79 #define POWER(exponent, input_val) exponent < 0 ? \ 80 (int)((int) (input_val) << (exponent*(-1))): \ 81 (int)((int) (input_val*1000000) >> exponent)/1000000 82 83 static i2c_ltc_t* sense_resistor_config; 84 85 /* Sense Resistors Configuration Table for Tomahawk 56960k */ 86 static i2c_ltc_t sense_resistor_config_56960k[MAX_VS_CONFIG]={ 87 { 0, "1.25", "ltc3880", I2C_LTC3880_CH0, LTC3880_1_25V_RES_CONFIG, 0 }, 88 { 1, "1.8", "ltc3880", I2C_LTC3880_CH1, LTC3880_1_8V_RES_CONFIG, 0 }, 89 { 2, "Analog", "ltc3882-1", I2C_BOTH_CH, LTC3882_ANLG_RES_CONFIG, 0 }, 90 { 3, "3.3", "ltc3882-0", I2C_BOTH_CH, LTC3882_3_3V_RES_CONFIG, 0 }, 91 { 4, "Core", I2C_LTC3882_55, I2C_BOTH_CH, 1, 0 }, 92 { 5, "ANA1", I2C_LTC3880_41, I2C_BOTH_CH, 2, 0 }, 93 { 6, "ANA2", I2C_LTC3880_42, I2C_LTC3880_CH0, 2, 0 }, 94 { 7, "3.3V", I2C_LTC3880_42, I2C_LTC3880_CH1, 4, 0 }, 95 { 8, "DDR_15", I2C_LTC3880_43, I2C_BOTH_CH, 2, 0 }, 96 { 9, "SP1", I2C_LTC3880_47, I2C_LTC3880_CH0, 8, 0 }, 97 { 10, "SP2", I2C_LTC3880_47, I2C_LTC3880_CH1, 4, 0 }, 98 { 11, "DDR_Core", I2C_LTC3880_45, I2C_LTC3880_CH0, 8, 0 }, 99 { 12, "SP3", I2C_LTC3880_45, I2C_LTC3880_CH1, 4, 0 }, 100 { 13, "Core", I2C_LTC3882_66, I2C_BOTH_CH, 1, 0 }, 101 { 14, "Core", I2C_LTC3882_77, I2C_BOTH_CH, 1, 0 } 102 }; 103 104 static i2c_ltc_t sense_resistor_config_56260[SB2_MAX_VS_CONFIG]={ 105 { 0, "Core", I2C_LTC3880_41, I2C_LTC3880_CH0, LTC3880_CORE_RES_CONFIG, 0 }, 106 { 1, "DDR", I2C_LTC3880_41, I2C_LTC3880_CH1, LTC3880_DDR_RES_CONFIG, 0 }, 107 { 2, "IPROC_CORE", I2C_LTC3880_42, I2C_LTC3880_CH0, LTC3880_IPROC_CORE_RES_CONFIG, 0 }, 108 { 3, "Analog", I2C_LTC3880_42, I2C_LTC3880_CH1, LTC3880_ANLG_RES_CONFIG, 0 }, 109 { 4, "1.8", I2C_LTM4676_43, I2C_LTC3880_CH1, LTC3880_1_8V_RES_CONFIG, 0 }, 110 { 5, "3.3", I2C_LTM4676_43, I2C_LTC3880_CH0, LTC3880_3_3V_RES_CONFIG, 0 }, 111 }; 112 #ifdef BCM_APACHE_SUPPORT 113 /* Sense Resistors Configuration Table for Apache 56560K and Maverick 56760K*/ 114 static i2c_ltc_t sense_resistor_config_56760[AP_MAX_VS_CONFIG]={ 115 { 0, "Core", I2C_LTC3884_42, I2C_BOTH_CH, 1, 0 }, 116 { 1, "Core", I2C_LTC3884_43, I2C_LTC3880_CH0, 1, 0 }, 117 { 2, "Analog", I2C_LTC3884_43, I2C_LTC3880_CH1, 2, 0 }, 118 { 3, "3.3V", I2C_LTC3880_45, I2C_BOTH_CH, 2, 0 }, 119 }; 120 /* Sense Resistors Configuration Table for FireBolt5 56565K */ 121 static i2c_ltc_t sense_resistor_config_56565[FB5_MAX_VS_CONFIG]={ 122 { 0, "Core", I2C_LTC3884_42, I2C_BOTH_CH, 1, 0 }, 123 { 1, "Core", I2C_LTC3884_43, I2C_LTC3880_CH0, 1, 0 }, 124 { 2, "Analog", I2C_LTC3884_43, I2C_LTC3880_CH1, 2, 0 }, 125 { 3, "1.0V_PHY", I2C_LTC3884_46, I2C_BOTH_CH, 1, 0 }, 126 { 4, "3.3V", I2C_LTM4676_47, I2C_BOTH_CH, 0, 1 }, 127 }; 128 #endif 129 130 #ifdef BCM_MONTEREY_SUPPORT 131 /* Sense Resistors Configuration Table for MONTEREY 56670*/ 132 static i2c_ltc_t sense_resistor_config_56670[MN_MAX_VS_CONFIG]={ 133 { 0, "Core", I2C_LTC3884_42, I2C_BOTH_CH, 1, 0 }, 134 { 2, "Analog", I2C_LTC3884_43, I2C_LTC3880_CH1, 2, 0 }, 135 { 3, "3.3V", I2C_LTC3884_43, I2C_LTC3880_CH0, 1, 0 }, 136 }; 137 #endif 138 139 #ifdef BCM_HELIX5_SUPPORT 140 /* Sense Resistors Configuration Table for FireBolt5 56565K */ 141 static i2c_ltc_t sense_resistor_config_56370[HX5_MAX_VS_CONFIG]={ 142 { 0, "Core", I2C_LTC3884_42, I2C_BOTH_CH, 1, 0 }, 143 { 1, "Core", I2C_LTC3884_43, I2C_LTC3880_CH0, 1, 0 }, 144 { 2, "Analog", I2C_LTC3884_43, I2C_LTC3880_CH1, 2, 0 }, 145 }; 146 #endif 147 148 static i2c_ltc_t sense_resistor_config_56160[HR3_MAX_VS_CONFIG]={ 149 {0, "3.3V", I2C_LTC3880_60, I2C_LTC3880_CH0, 2, 0}, 150 {1, "1.0V", I2C_LTC3880_60, I2C_LTC3880_CH1, 2, 0}, 151 {2, "1.8V", I2C_LTC3880_61, I2C_LTC3880_CH0, 2, 0}, 152 {3, "1.2V", I2C_LTC3880_61, I2C_LTC3880_CH1, 2, 0}, 153 {4, "Core", I2C_LTC3880_62, I2C_LTC3880_CH0, 2, 0}, 154 {5, "Analog", I2C_LTC3880_62, I2C_LTC3880_CH1, 2, 0}, 155 }; 156 157 static i2c_ltc_t sense_resistor_config_53570[GH2_MAX_VS_CONFIG]={ 158 {0, "3.3V", I2C_LTC3880_60, I2C_LTC3880_CH0, 2, 0}, 159 {1, "1.25V", I2C_LTC3880_60, I2C_LTC3880_CH1, 2, 0}, 160 {2, "1.8V", I2C_LTC3880_61, I2C_LTC3880_CH0, 2, 0}, 161 {3, "1.2V", I2C_LTC3880_61, I2C_LTC3880_CH1, 2, 0}, 162 {4, "Core", I2C_LTC3880_62, I2C_LTC3880_CH0, 2, 0}, 163 {5, "Analog", I2C_LTC3880_62, I2C_LTC3880_CH1, 2, 0}, 164 }; 165 166 static i2c_ltc_t sense_resistor_config_53570S[GH2_MAX_VS_CONFIG]={ 167 {0, "3.3V", I2C_LTC3880_60, I2C_LTC3880_CH0, 2, 0}, 168 {1, "1.25V", I2C_LTC3880_60, I2C_LTC3880_CH1, 2, 0}, 169 {2, "1.8V", I2C_LTC3880_61, I2C_LTC3880_CH0, 2, 0}, 170 {3, "1.5V", I2C_LTC3880_61, I2C_LTC3880_CH1, 2, 0}, 171 {4, "Core", I2C_LTC3880_62, I2C_LTC3880_CH0, 2, 0}, 172 {5, "Analog", I2C_LTC3880_62, I2C_LTC3880_CH1, 2, 0}, 173 }; 174 175 static i2c_ltc_t sense_resistor_config_53547[WH2_MAX_VS_CONFIG]={ 176 {0, "3.3V", I2C_LTC3880_60, I2C_LTC3880_CH0, 2, 0}, 177 {1, "1.8V", I2C_LTC3880_61, I2C_LTC3880_CH0, 2, 0}, 178 {2, "1.2V", I2C_LTC3880_61, I2C_LTC3880_CH1, 2, 0}, 179 {3, "Core", I2C_LTC3880_62, I2C_LTC3880_CH0, 2, 0}, 180 {4, "Analog", I2C_LTC3880_62, I2C_LTC3880_CH1, 2, 0}, 181 }; 182 183 static i2c_ltc_t sense_resistor_config_53549[WH2_MAX_VS_CONFIG]={ 184 {0, "3.3V", I2C_LTC3880_60, I2C_LTC3880_CH0, 2, 0}, 185 {1, "1.8V", I2C_LTC3880_61, I2C_LTC3880_CH0, 2, 0}, 186 {2, "1.5V", I2C_LTC3880_61, I2C_LTC3880_CH1, 2, 0}, 187 {3, "Core", I2C_LTC3880_62, I2C_LTC3880_CH0, 2, 0}, 188 {4, "Analog", I2C_LTC3880_62, I2C_LTC3880_CH1, 2, 0}, 189 }; 190 191 typedef struct _ltc_board_resistor_map_s { 192 int offset; 193 i2c_ltc_t* sense_resistor_config; 194 } _ltc_board_resistor_map_t; 195 196 /* 197 * This table is used to reflect the mapping between board type offset and 198 * sens_register_config table. The board type offset is used since the IN 199 * parameter on I2C_LTC_IOC_{SET_CONFIG,SET_RCONFIG,READ_IOUT} takes TH SVK 200 * board(G42) as basis to identify different board. 201 * 202 * Information for the board type offset : 203 * 1. This is the delta value of board_type index and TH is the index basis. 204 * [Examples] : 205 * - Tomahawk(board_type=G42), offset=0 206 * - HR3 (board_type=G52~G55, offset=10 (G42-G52) 207 * 2. The board_type definition can be found in i2c_cmds.c 208 */ 209 static _ltc_board_resistor_map_t board_resistor_map[] = { 210 {0, sense_resistor_config_56960k}, /* TH(G42) */ 211 {7, sense_resistor_config_56960k}, /* TH(G49) */ 212 {6, sense_resistor_config_56260}, /* SB2(G48) */ 213 {10, sense_resistor_config_56160}, /* HR3(G52) */ 214 {11, sense_resistor_config_56160}, /* HR3(G53) */ 215 {12, sense_resistor_config_56160}, /* HR3(G54) */ 216 {13, sense_resistor_config_56160}, /* HR3(G55) */ 217 {16, sense_resistor_config_53570}, /* GH2(G58) */ 218 {17, sense_resistor_config_53570S}, /* GH2(G59) */ 219 {20, sense_resistor_config_53547}, /* WH2(G62) */ 220 {21, sense_resistor_config_53549}, /* WH2(G63) */ 221 }; 222 223 /* 224 * This function is used to match the comming offset (delta_index) with a 225 * predefined sense_resistor_configuration table. 226 */ 227 STATIC int 228 ltc388x_board_resistor_match(int unit, int in_offset) 229 { 230 int i, map_size; 231 232 #ifdef BCM_APACHE_SUPPORT 233 if ((SOC_CONTROL(unit)->board_type == 0x94) || 234 (SOC_CONTROL(unit)->board_type == 0x96)) { 235 return SOC_E_NONE; 236 } 237 #endif 238 239 #ifdef BCM_MONTEREY_SUPPORT 240 if ((SOC_CONTROL(unit)->board_type == 0xAA)) { 241 return SOC_E_NONE; 242 } 243 #endif 244 245 #ifdef BCM_HELIX5_SUPPORT 246 if ((SOC_CONTROL(unit)->board_type == 0xB0) || (SOC_CONTROL(unit)->board_type == 0xB3) || 247 (SOC_CONTROL(unit)->board_type == 0xB6)) { 248 return SOC_E_NONE; 249 } 250 #endif 251 252 map_size = sizeof(board_resistor_map) / sizeof(_ltc_board_resistor_map_t); 253 254 for (i = 0; i < map_size; i++) { 255 if (board_resistor_map[i].offset == in_offset) { 256 sense_resistor_config = board_resistor_map[i].sense_resistor_config; 257 return SOC_E_NONE; 258 } 259 } 260 return SOC_E_NOT_FOUND; 261 } 262 263 /* 264 * Convert a floating point value into a 265 * LinearFloat5_11 formatted word 266 */ 267 268 STATIC int 269 #ifdef COMPILER_HAS_DOUBLE 270 ltc388x_float_to_L11(double input_val, uint16* data) 271 #else 272 ltc388x_float_to_L11(int input_val, uint16* data) 273 #endif 274 { 275 uint16 uExponent, uMantissa; 276 /* set exponent to -16 */ 277 int16 exponent = -16; 278 /* extract mantissa from input value */ 279 int mantissa = POWER(exponent, input_val); 280 281 /* Search for an exponent that produces 282 * a valid 11-bit mantissa */ 283 do 284 { 285 if((mantissa >= -1024) && 286 (mantissa <= +1023)) 287 { 288 break; /* stop if mantissa valid */ 289 } 290 exponent++; 291 mantissa= POWER(exponent, input_val); 292 } while (exponent < +15); 293 294 /* Format the exponent of the L11 */ 295 uExponent = exponent << 11; 296 /* Format the mantissa of the L11 */ 297 uMantissa = mantissa & 0x07FF; 298 /* Compute value as exponent | mantissa */ 299 *(data) = uExponent | uMantissa; 300 return SOC_E_NONE; 301 } 302 303 /* 304 * Convert a LinearFloat5_11 formatted word 305 * into a floating point value 306 */ 307 STATIC int 308 ltc388x_L11_to_float(uint16 input_val, void *data) 309 { 310 /* extract exponent as MS 5 bits */ 311 int8 exponent = input_val >> 11; 312 /* extract mantissa as LS 11 bits */ 313 int16 mantissa = input_val & 0x7ff; 314 /* sign extend exponent from 5 to 8 bits */ 315 if( exponent > 0x0F ) exponent |= 0xE0; 316 /* sign extend mantissa from 11 to 16 bits */ 317 if( mantissa > 0x03FF ) mantissa |= 0xF800; 318 #ifdef COMPILER_HAS_DOUBLE 319 /* compute value as mantissa * 2^(exponent) */ 320 *(double *)data= exponent < 0 ? 321 (double) ((mantissa*1000000) >> 322 (exponent* (-1)))/1000000: 323 (double) (mantissa << exponent); 324 #else 325 *(int *)data= exponent < 0 ? 326 (((mantissa)*1000000) >> (exponent*(-1))): 327 ((mantissa) << exponent)*100000; 328 #endif 329 return SOC_E_NONE; 330 } 331 332 STATIC int 333 ltc388x_wait_for_not_busy(int unit, int devno) 334 { 335 int rv = SOC_E_NONE; 336 uint8 mfr_status, saddr; 337 uint32 usec, wait_usec; 338 i2c_device_t *dev = soc_i2c_device(unit, devno); 339 340 DEV_CHECK_RETURN(dev); 341 342 wait_usec = 0; 343 usec = 10; 344 345 saddr = soc_i2c_addr(unit, devno); 346 347 while(wait_usec < 1000000) { 348 SOC_IF_ERROR_RETURN(soc_i2c_read_byte_data(unit, saddr, 349 PMBUS_CMD_MFR_COMMON, &mfr_status)); 350 dev->rbyte++; 351 if ((mfr_status & 0x70) == 0x70) { 352 /* Bit 6 : Chip not busy */ 353 /* Bit 5 : calculations not pending */ 354 /* Bit 4 : OUTPUT not in transition */ 355 break; 356 } else { 357 sal_udelay(usec); 358 wait_usec += usec; 359 } 360 } 361 362 if ((mfr_status & 0x70) != 0x70) { 363 LOG_WARN(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "unit %d i2c %s :" 364 "ltc388x is busy !\n"), 365 unit, soc_i2c_devname(unit, devno))); 366 rv = SOC_E_TIMEOUT; 367 } 368 369 return rv; 370 } 371 372 STATIC int 373 ltc388x_read(int unit, int devno, uint16 addr, uint8* data, uint32* len) 374 { 375 int rv = SOC_E_NONE; 376 uint8 saddr; 377 i2c_device_t *dev = soc_i2c_device(unit, devno); 378 379 DEV_CHECK_RETURN(dev); 380 381 saddr = soc_i2c_addr(unit, devno); 382 383 if (*len == 0) { 384 return SOC_E_NONE; 385 } 386 387 if (*len == 1) { 388 /* reads a single byte from a device, from a designated register*/ 389 rv = soc_i2c_read_byte_data(unit, saddr, addr, data); 390 dev->rbyte++; 391 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 392 "unit %d i2c %s: LTC388X_read: " 393 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d, " 394 "rv = %d\n"), 395 unit, soc_i2c_devname(unit,devno), 396 saddr, addr, *data, *len, rv)); 397 } else if (*len == 2) { 398 /* reads a single word from a device, from a designated register*/ 399 rv = soc_i2c_read_word_data(unit, saddr, addr,(uint16 *)data); 400 dev->rbyte +=2; 401 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 402 "unit %d i2c %s: LTC388X_read: " 403 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d, " 404 "rv = %d\n"), 405 unit, soc_i2c_devname(unit,devno), 406 saddr, addr, *(uint16 *)data, *len, rv)); 407 } else { 408 /* not supported for now */ 409 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 410 "unit %d i2c %s: LTC388X_read fail: " 411 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d\n"), 412 unit, soc_i2c_devname(unit,devno), 413 saddr, addr, *data, *len)); 414 } 415 416 return rv; 417 } 418 419 STATIC int 420 ltc388x_write(int unit, int devno, uint16 addr, uint8* data, uint32 len) 421 { 422 int rv = SOC_E_NONE; 423 uint8 saddr; 424 unsigned short val; 425 i2c_device_t *dev = soc_i2c_device(unit, devno); 426 427 DEV_CHECK_RETURN(dev); 428 429 saddr = soc_i2c_addr(unit, devno); 430 431 if (len == 0) { 432 /* simply writes command code to device */ 433 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, "i2c %s: LTC388X write: " 434 "saddr = 0x%x, addr = 0x%x, len = %d\n"), 435 soc_i2c_devname(unit, devno), saddr, addr, len)); 436 rv = soc_i2c_write_byte(unit, saddr, addr); 437 } else if (len == 1) { 438 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, "i2c %s: LTC388X write: " 439 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d\n"), 440 soc_i2c_devname(unit, devno), saddr, addr, *data, len)); 441 rv = soc_i2c_write_byte_data(unit, saddr, addr,*data); 442 dev->tbyte++; 443 } else if (len == 2) { 444 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, "i2c %s: LTC388X write: " 445 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d\n"), 446 soc_i2c_devname(unit, devno), 447 saddr, addr, *(uint16 *)data, len)); 448 val = *(unsigned short *)data; 449 rv = soc_i2c_write_word_data(unit, saddr, addr, val); 450 dev->tbyte += 2; 451 } 452 453 if (addr == PMBUS_CMD_VOUT_COMMAND) { 454 /* Make sure the set voltage command is completed internally */ 455 rv = ltc388x_wait_for_not_busy(unit, devno); 456 if (rv == SOC_E_NONE) { 457 sal_usleep(120000); 458 } 459 } 460 return rv; 461 } 462 463 464 STATIC int 465 ltc388x_check_page(int unit, int devno, int ch) 466 { 467 int rv; 468 uint8 page; 469 uint32 len; 470 471 len = sizeof(char); 472 rv = ltc388x_read(unit, devno, PMBUS_CMD_PAGE, &page, &len); 473 if (rv != SOC_E_NONE) { 474 return rv; 475 } 476 477 if (page != ch) { 478 page = ch; 479 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 480 "LTC388X %d set page to %d\n"), 481 soc_i2c_addr(unit, devno), page)); 482 rv = ltc388x_write(unit, devno, PMBUS_CMD_PAGE, &page, sizeof(char)); 483 } 484 485 return rv; 486 } 487 488 489 490 STATIC int 491 ltc388x_setmin_max(int unit, int devno, int len) 492 { 493 int rv=SOC_E_NONE; 494 int data,i,ch; 495 uint16 dac; 496 i2c_device_t *dev = soc_i2c_device(unit, devno); 497 int max_vs_config = MAX_VS_CONFIG; 498 499 DEV_PRIVDATA_CHECK_RETURN(dev); 500 #if defined(BCM_SABER2_SUPPORT) 501 if(SOC_IS_SABER2(unit)) { 502 max_vs_config = sizeof(sense_resistor_config_56260)/sizeof(i2c_ltc_t); 503 } 504 #endif 505 #if defined(BCM_APACHE_SUPPORT) 506 if (SOC_CONTROL(unit)->board_type == 0x94) { 507 max_vs_config = sizeof(sense_resistor_config_56760)/sizeof(i2c_ltc_t); 508 } else if (SOC_CONTROL(unit)->board_type == 0x96) { 509 max_vs_config = sizeof(sense_resistor_config_56565)/sizeof(i2c_ltc_t); 510 } 511 #endif 512 513 #if defined(BCM_MONTEREY_SUPPORT) 514 if (SOC_CONTROL(unit)->board_type == 0xAA) { 515 max_vs_config = sizeof(sense_resistor_config_56670)/sizeof(i2c_ltc_t); 516 } 517 #endif 518 519 #if defined(BCM_HELIX5_SUPPORT) 520 if ((SOC_CONTROL(unit)->board_type == 0xB0) || (SOC_CONTROL(unit)->board_type == 0xB3) || 521 (SOC_CONTROL(unit)->board_type == 0xB6)) { 522 max_vs_config = sizeof(sense_resistor_config_56370)/sizeof(i2c_ltc_t); 523 } 524 #endif 525 /* for HR3 boards */ 526 if ((SOC_CONTROL(unit)->board_type == 0x8F) || 527 (SOC_CONTROL(unit)->board_type == 0x90) || 528 (SOC_CONTROL(unit)->board_type == 0x91)) { 529 max_vs_config = sizeof(sense_resistor_config_56160)/sizeof(i2c_ltc_t); 530 } 531 532 /* for GH2 boards */ 533 if ((SOC_CONTROL(unit)->board_type == 0xA0) || 534 (SOC_CONTROL(unit)->board_type == 0xA1)) { 535 max_vs_config = sizeof(sense_resistor_config_56160)/sizeof(i2c_ltc_t); 536 } 537 538 /* for WH2 boards */ 539 if ((SOC_CONTROL(unit)->board_type == 0xA8) || 540 (SOC_CONTROL(unit)->board_type == 0xA9)) { 541 max_vs_config = sizeof(sense_resistor_config_53547)/sizeof(i2c_ltc_t); 542 } 543 544 for(i=0;i<max_vs_config;i++) { 545 if (sal_strcmp(DEV_DAC_PARAMS(dev)[len].name, 546 sense_resistor_config[i].function) == 0) { 547 break; 548 } 549 } 550 if (i == max_vs_config) { 551 LOG_CLI((BSL_META_U(unit, "Error: failed to find sense resistor " 552 "for VDD_%s in LTC 3880 device.\n"), 553 DEV_DAC_PARAMS(dev)[len].name)); 554 return SOC_E_NOT_FOUND; 555 } 556 if (sense_resistor_config[i].flag == 0) { 557 ch=sense_resistor_config[i].ch; 558 SOC_IF_ERROR_RETURN 559 (ltc388x_check_page(unit, devno, ch)); 560 data = DEV_DAC_PARAMS(dev)[len].dac_max_hwval; 561 dac=(uint16) L16_RANGE_UPPER(data, 10000); 562 SOC_IF_ERROR_RETURN 563 (ltc388x_write(unit, devno, PMBUS_CMD_VOUT_MAX, (void *)&dac, 2)); 564 dac=(uint16) L16_RANGE_UPPER(data, 7000); 565 SOC_IF_ERROR_RETURN 566 (ltc388x_wait_for_not_busy(unit, devno)); 567 SOC_IF_ERROR_RETURN 568 (ltc388x_write(unit, devno, PMBUS_CMD_VOUT_OV_FAULT_LIMIT, 569 (void *)&dac, 2)); 570 dac=(uint16) L16_RANGE_UPPER(data, 5000); 571 SOC_IF_ERROR_RETURN 572 (ltc388x_wait_for_not_busy(unit, devno)); 573 SOC_IF_ERROR_RETURN 574 (ltc388x_write(unit, devno, PMBUS_CMD_VOUT_OV_WARN_LIMIT, 575 (void *)&dac, 2)); 576 dac=(uint16) L16_RANGE_UPPER(data, 2000); 577 SOC_IF_ERROR_RETURN 578 (ltc388x_wait_for_not_busy(unit, devno)); 579 SOC_IF_ERROR_RETURN 580 (ltc388x_write(unit, devno, PMBUS_CMD_VOUT_MARGIN_HIGH, 581 (void *)&dac, 2)); 582 583 data=DEV_DAC_PARAMS(dev)[len].dac_min_hwval; 584 SOC_IF_ERROR_RETURN 585 (ltc388x_wait_for_not_busy(unit, devno)); 586 587 dac=(uint16) L16_RANGE_LOWER(data, 5000); 588 SOC_IF_ERROR_RETURN 589 (ltc388x_write(unit, devno, PMBUS_CMD_VOUT_UV_FAULT_LIMIT, 590 (void *)&dac, 2)); 591 592 if((sal_strcmp("ltc3880", sense_resistor_config[i].devname) == 0) || 593 (sal_strcmp(I2C_LTM4676_43, sense_resistor_config[i].devname) == 0)){ 594 SOC_IF_ERROR_RETURN 595 (ltc388x_write(unit, devno, PMBUS_CMD_POWER_GOOD_ON, 596 (void *)&dac, 2)); 597 598 dac=(uint16) L16_RANGE_LOWER(data, 7000); 599 SOC_IF_ERROR_RETURN 600 (ltc388x_write(unit, devno, PMBUS_CMD_POWER_GOOD_OFF, 601 (void *)&dac, 2)); 602 } 603 dac=(uint16) L16_RANGE_LOWER(data, 2000); 604 SOC_IF_ERROR_RETURN 605 (ltc388x_wait_for_not_busy(unit, devno)); 606 SOC_IF_ERROR_RETURN 607 (ltc388x_write(unit, devno, PMBUS_CMD_VOUT_UV_WARN_LIMIT, 608 (void *)&dac, 2)); 609 610 dac=(uint16) L16_RANGE_LOWER(data, 1000); 611 SOC_IF_ERROR_RETURN 612 ( ltc388x_wait_for_not_busy(unit, devno)); 613 SOC_IF_ERROR_RETURN 614 (ltc388x_write(unit, devno, PMBUS_CMD_VOUT_MARGIN_LOW, 615 (void *)&dac, 2)); 616 617 #if defined(BCM_SABER2_SUPPORT) 618 if(!SOC_IS_SABER2(unit)) { 619 #endif 620 rv=ltc388x_float_to_L11(sense_resistor_config[i].res_value, &dac); 621 SOC_IF_ERROR_RETURN 622 (ltc388x_write(unit, devno, 623 PMBUS_CMD_IOUT_CAL_GAIN, (void *)&dac, 2)); 624 sal_udelay(500); 625 #if defined(BCM_SABER2_SUPPORT) 626 } 627 #endif 628 629 /* Device Configured */ 630 sense_resistor_config[i].flag=1; 631 632 } 633 return rv; 634 } 635 636 STATIC int 637 ltc388x_get_ch_voltage(int unit, int devno, int ch, unsigned short *voltage) 638 { 639 int rv; 640 uint32 len; 641 642 SOC_IF_ERROR_RETURN(ltc388x_check_page(unit, devno, ch)); 643 644 len = sizeof(short); 645 rv = ltc388x_read(unit, devno, PMBUS_CMD_READ_VOUT, (uint8*)voltage, 646 &len); 647 648 return rv; 649 } 650 651 STATIC int 652 ltc388x_set_ch_voltage_upper_with_supervision(int unit, int devno, int ch, 653 unsigned short voltage) 654 { 655 unsigned short val; 656 657 val = L16_RANGE_UPPER(voltage, FAULT_LIMIT_RANGE); 658 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 659 PMBUS_CMD_VOUT_OV_FAULT_LIMIT, 660 (uint8*)&val, sizeof(short))); 661 662 val = L16_RANGE_UPPER(voltage, WARN_LIMIT_RANGE); 663 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 664 PMBUS_CMD_VOUT_OV_WARN_LIMIT, 665 (uint8*)&val, sizeof(short))); 666 667 val = L16_RANGE_UPPER(voltage, MARGIN_RANGE); 668 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 669 PMBUS_CMD_VOUT_MARGIN_HIGH, 670 (uint8*)&val, sizeof(short))); 671 672 673 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, PMBUS_CMD_VOUT_COMMAND, 674 (uint8*)&voltage, sizeof(short))); 675 676 val = L16_RANGE_LOWER(voltage, MARGIN_RANGE); 677 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 678 PMBUS_CMD_VOUT_MARGIN_LOW, 679 (uint8*)&val, sizeof(short))); 680 681 682 val = L16_RANGE_LOWER(voltage, WARN_LIMIT_RANGE); 683 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 684 PMBUS_CMD_VOUT_UV_WARN_LIMIT, 685 (uint8*)&val, sizeof(short))); 686 687 val = L16_RANGE_LOWER(voltage, FAULT_LIMIT_RANGE); 688 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 689 PMBUS_CMD_VOUT_UV_FAULT_LIMIT, 690 (uint8*)&val, sizeof(short))); 691 692 if (soc_i2c_devtype(unit, devno) != LTC3884_DEVICE_TYPE) { 693 val = L16_RANGE_LOWER(voltage, POWER_GOOD_ON_RANGE); 694 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 695 PMBUS_CMD_POWER_GOOD_ON, 696 (uint8*)&val, sizeof(short))); 697 698 val = L16_RANGE_LOWER(voltage, POWER_GOOD_OFF_RANGE); 699 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 700 PMBUS_CMD_POWER_GOOD_OFF, 701 (uint8*)&val, sizeof(short))); 702 } 703 704 return SOC_E_NONE; 705 } 706 707 STATIC int 708 ltc388x_set_ch_voltage_lower_with_supervision(int unit, int devno, int ch, 709 unsigned short voltage) 710 { 711 unsigned short val; 712 713 val = L16_RANGE_LOWER(voltage, FAULT_LIMIT_RANGE); 714 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 715 PMBUS_CMD_VOUT_UV_FAULT_LIMIT, 716 (uint8*)&val, sizeof(short))); 717 718 val = L16_RANGE_LOWER(voltage, WARN_LIMIT_RANGE); 719 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 720 PMBUS_CMD_VOUT_UV_WARN_LIMIT, 721 (uint8*)&val, sizeof(short))); 722 723 val = L16_RANGE_LOWER(voltage, MARGIN_RANGE); 724 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 725 PMBUS_CMD_VOUT_MARGIN_LOW, 726 (uint8*)&val, sizeof(short))); 727 728 if (soc_i2c_devtype(unit, devno) != LTC3884_DEVICE_TYPE) { 729 val = L16_RANGE_LOWER(voltage, POWER_GOOD_ON_RANGE); 730 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 731 PMBUS_CMD_POWER_GOOD_ON, 732 (uint8*)&val, sizeof(short))); 733 734 val = L16_RANGE_LOWER(voltage, POWER_GOOD_OFF_RANGE); 735 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 736 PMBUS_CMD_POWER_GOOD_OFF, 737 (uint8*)&val, sizeof(short))); 738 739 } 740 741 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, PMBUS_CMD_VOUT_COMMAND, 742 (uint8*)&voltage, sizeof(short))); 743 744 745 val = L16_RANGE_UPPER(voltage, MARGIN_RANGE); 746 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 747 PMBUS_CMD_VOUT_MARGIN_HIGH, 748 (uint8*)&val, sizeof(short))); 749 750 val = L16_RANGE_UPPER(voltage, WARN_LIMIT_RANGE); 751 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 752 PMBUS_CMD_VOUT_OV_WARN_LIMIT, 753 (uint8*)&val, sizeof(short))); 754 755 val = L16_RANGE_UPPER(voltage, FAULT_LIMIT_RANGE); 756 SOC_IF_ERROR_RETURN(ltc388x_write(unit, devno, 757 PMBUS_CMD_VOUT_OV_FAULT_LIMIT, 758 (uint8*)&val, sizeof(short))); 759 760 return SOC_E_NONE; 761 } 762 763 STATIC int 764 ltc388x_set_ch_voltage(int unit, int devno, int ch, unsigned short voltage) 765 { 766 int rv = SOC_E_NONE; 767 unsigned short old_vout; 768 769 SOC_IF_ERROR_RETURN(ltc388x_get_ch_voltage(unit, devno, ch, &old_vout)); 770 771 if (voltage >= old_vout) { 772 SOC_IF_ERROR_RETURN(ltc388x_set_ch_voltage_upper_with_supervision(unit, 773 devno, ch, voltage)); 774 } else { 775 SOC_IF_ERROR_RETURN(ltc388x_set_ch_voltage_lower_with_supervision(unit, 776 devno, ch, voltage)); 777 } 778 779 780 /* 781 if (SOC_SUCCESS(rv)) { 782 sal_udelay(100000); 783 } 784 */ 785 786 return rv; 787 } 788 789 STATIC int 790 ltc388x_dac_set_ch_voltage(int unit, int devno, int ch, unsigned short voltage) 791 { 792 int rv; 793 i2c_device_t *dev = soc_i2c_device(unit, devno); 794 795 DEV_PRIVDATA_CHECK_RETURN(dev); 796 797 rv = ltc388x_set_ch_voltage(unit, devno, ch, voltage); 798 799 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) 800 if ((SOC_CONTROL(unit)->board_type == 0x94) || 801 (SOC_CONTROL(unit)->board_type == 0x96) || 802 (SOC_CONTROL(unit)->board_type == 0xB0) || 803 (SOC_CONTROL(unit)->board_type == 0xB3) || 804 (SOC_CONTROL(unit)->board_type == 0xB6)) { 805 /* For Apache/Maverick/FB5 Core voltage is on 3 phase so old voltage 806 * needs to be saved only for the device connected on first two phases 807 * which is done in ioctl() 808 */ 809 return rv; 810 } 811 #endif /* #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) */ 812 813 if (SOC_SUCCESS(rv)) { 814 /* Keep last value since DAC is write-only device */ 815 DEV_DAC_PARAMS(dev)[ch].dac_last_val = voltage; 816 } 817 818 return rv; 819 } 820 821 STATIC int 822 ltc388x_read_current(int unit, int devno, void* data, int ch) 823 { 824 int rv = SOC_E_NONE; 825 #ifdef COMPILER_HAS_DOUBLE 826 double fval,fval1,fval0; 827 #else 828 int fval,fval1,fval0; 829 #endif 830 uint16 dac,dac0,dac1; 831 uint32 datalen; 832 soc_i2c_bus_t *i2cbus; 833 int i; 834 int max_vs_config = MAX_VS_CONFIG; 835 836 #if defined(BCM_SABER2_SUPPORT) 837 if(SOC_IS_SABER2(unit)) { 838 max_vs_config = sizeof(sense_resistor_config_56260)/sizeof(i2c_ltc_t); 839 } 840 #endif 841 #if defined(BCM_APACHE_SUPPORT) 842 if (SOC_CONTROL(unit)->board_type == 0x94) { 843 max_vs_config = sizeof(sense_resistor_config_56760)/sizeof(i2c_ltc_t); 844 } else if (SOC_CONTROL(unit)->board_type == 0x96) { 845 max_vs_config = sizeof(sense_resistor_config_56565)/sizeof(i2c_ltc_t); 846 } 847 #endif 848 849 #if defined(BCM_MONTEREY_SUPPORT) 850 if (SOC_CONTROL(unit)->board_type == 0xAA) { 851 max_vs_config = sizeof(sense_resistor_config_56670)/sizeof(i2c_ltc_t); 852 } 853 #endif 854 855 #if defined(BCM_HELIX5_SUPPORT) 856 if ((SOC_CONTROL(unit)->board_type == 0xB0) || (SOC_CONTROL(unit)->board_type == 0xB3) || 857 (SOC_CONTROL(unit)->board_type == 0xB6)) { 858 max_vs_config = sizeof(sense_resistor_config_56370)/sizeof(i2c_ltc_t); 859 } 860 #endif 861 862 /* for HR3 boards */ 863 if ((SOC_CONTROL(unit)->board_type == 0x8F) || 864 (SOC_CONTROL(unit)->board_type == 0x90) || 865 (SOC_CONTROL(unit)->board_type == 0x91)) { 866 max_vs_config = sizeof(sense_resistor_config_56160)/sizeof(i2c_ltc_t); 867 } 868 869 /* for GH2 boards */ 870 if ((SOC_CONTROL(unit)->board_type == 0xA0) || 871 (SOC_CONTROL(unit)->board_type == 0xA1)) { 872 max_vs_config = sizeof(sense_resistor_config_56160)/sizeof(i2c_ltc_t); 873 } 874 875 /* for WH2 boards */ 876 if ((SOC_CONTROL(unit)->board_type == 0xA8) || 877 (SOC_CONTROL(unit)->board_type == 0xA9)) { 878 max_vs_config = sizeof(sense_resistor_config_53547)/sizeof(i2c_ltc_t); 879 } 880 881 i2cbus = I2CBUS(unit); 882 for( i=0; i < max_vs_config; i++ ) { 883 if (sal_strcmp(i2cbus->devs[devno]->devname, 884 sense_resistor_config[i].devname) == 0) { 885 if (sense_resistor_config[i].ch == ch ) { 886 if (sense_resistor_config[i].flag == 0) { 887 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 888 LOG_CLI((BSL_META_U(unit, "Error: failed to set page" 889 " %d in unit:%d LTC388X device name: %s.\n"), 890 ch, unit, soc_i2c_devname(unit, devno))); 891 return rv; 892 } 893 894 #if defined(BCM_SABER2_SUPPORT) 895 if(!SOC_IS_SABER2(unit)) { 896 #endif 897 rv = ltc388x_float_to_L11( 898 sense_resistor_config[i].res_value, &dac); 899 if ((rv = ltc388x_write(unit, devno, 900 PMBUS_CMD_IOUT_CAL_GAIN, (void *)&dac, 2)) < 0) { 901 LOG_CLI((BSL_META_U(unit, "Error: failed to set " 902 "sense resistor in unit:%d" 903 " LTC388X device name: %s.\n"), 904 unit, soc_i2c_devname(unit, devno))); 905 return rv; 906 } 907 sal_udelay(500); 908 #if defined(BCM_SABER2_SUPPORT) 909 } 910 #endif 911 } 912 break; 913 } 914 } 915 } 916 if (i == max_vs_config) { 917 LOG_CLI((BSL_META_U(unit, "Error: failed to find sense resistor value " 918 "for %s device .\n"), soc_i2c_devname(unit, devno))); 919 return SOC_E_NOT_FOUND; 920 } 921 922 if( ch == 0xFF ) { 923 /* LTC3882/LTC3884 in dual mode hence current at both channels 924 * are added up to measure total output current.......*/ 925 ch = 0x00; 926 datalen = 2; 927 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 928 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 929 "unit: %d LTC388X device name: %s.\n"), 930 ch, unit, soc_i2c_devname(unit, devno))); 931 return rv; 932 } 933 if ((rv = ltc388x_read(unit, devno, PMBUS_CMD_READ_IOUT, 934 (void *)&dac0, &datalen)) < 0) { 935 LOG_CLI((BSL_META_U(unit, "Error: failed to read current in " 936 "LTC3882 device.\n"))); 937 } 938 ch = 0x01; 939 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 940 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 941 "unit: %d LTC388X device name: %s.\n"), 942 ch, unit, soc_i2c_devname(unit, devno))); 943 return rv; 944 } 945 if ((rv = ltc388x_read(unit, devno, PMBUS_CMD_READ_IOUT, 946 (void *)&dac1, &datalen)) < 0) { 947 LOG_CLI((BSL_META_U(unit, "Error: failed to read current in " 948 "unit: %d LTC3882 device name: %s.\n"), 949 unit, soc_i2c_devname(unit, devno))); 950 return rv; 951 } 952 rv = ltc388x_L11_to_float(dac1, &fval1); 953 rv = ltc388x_L11_to_float(dac0, &fval0); 954 fval = fval0 + fval1; 955 } else { 956 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 957 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 958 "unit: %d LTC388X device name: %s.\n"), 959 ch, unit, soc_i2c_devname(unit, devno))); 960 return rv; 961 } 962 datalen = 2; 963 if ((rv = ltc388x_read(unit, devno, 964 PMBUS_CMD_READ_IOUT, (void *)&dac, &datalen)) < 0) { 965 LOG_CLI((BSL_META_U(unit, "Error: failed to read current in " 966 "unit: %d LTC3882 device name: %s.\n"), 967 unit, soc_i2c_devname(unit, devno))); 968 return rv; 969 } 970 rv = ltc388x_L11_to_float(dac, &fval); 971 } 972 #ifdef COMPILER_HAS_DOUBLE 973 *(double *)data = fval * 1000; 974 #else 975 *(int *)data = fval; 976 #endif 977 return rv; 978 } 979 980 STATIC int 981 ltc388x_read_power(int unit, int devno, void* data, int ch) 982 { 983 int rv = SOC_E_NONE; 984 #ifdef COMPILER_HAS_DOUBLE 985 double fval,fval1,fval0; 986 #else 987 int fval,fval1,fval0; 988 #endif 989 uint16 dac,dac0,dac1; 990 uint32 datalen; 991 if( ch == 0xFF) { 992 /* LTC3882/LTC3884 in dual mode hence current at both channels 993 are added up to measure totl output current...........*/ 994 ch = 0x00; 995 datalen = 2; 996 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 997 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 998 "unit: %d LTC388X device name: %s.\n"), 999 ch, unit, soc_i2c_devname(unit, devno))); 1000 return rv; 1001 } 1002 if ((rv = ltc388x_read(unit, devno, PMBUS_CMD_READ_POUT, 1003 (void *)&dac0, &datalen)) < 0) { 1004 LOG_CLI((BSL_META_U(unit, "Error: failed to read current in " 1005 "LTC3882 device.\n"))); 1006 } 1007 ch = 0x01; 1008 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 1009 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1010 "unit: %d LTC388X device name: %s.\n"), 1011 ch, unit, soc_i2c_devname(unit, devno))); 1012 return rv; 1013 } 1014 if ((rv = ltc388x_read(unit, devno, PMBUS_CMD_READ_POUT, 1015 (void *)&dac1, &datalen)) < 0) { 1016 LOG_CLI((BSL_META_U(unit, "Error: failed to read power in " 1017 "unit: %d LTC3882 device name: %s.\n"), 1018 unit, soc_i2c_devname(unit, devno))); 1019 return rv; 1020 } 1021 rv = ltc388x_L11_to_float(dac1,&fval1); 1022 rv = ltc388x_L11_to_float(dac0,&fval0); 1023 fval = fval0+fval1; 1024 } else { 1025 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 1026 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1027 "unit: %d LTC388X device name: %s.\n"), 1028 ch, unit, soc_i2c_devname(unit, devno))); 1029 return rv; 1030 } 1031 datalen = 2; 1032 if ((rv = ltc388x_read(unit, devno, 1033 PMBUS_CMD_READ_POUT, (void *)&dac, &datalen)) < 0) { 1034 LOG_CLI((BSL_META_U(unit, "Error: failed to read power in " 1035 "unit: %d LTC3882 device name: %s.\n"), 1036 unit, soc_i2c_devname(unit, devno))); 1037 return rv; 1038 } 1039 rv = ltc388x_L11_to_float(dac,&fval); 1040 } 1041 #ifdef COMPILER_HAS_DOUBLE 1042 *(double *)data = fval * 1000; 1043 #else 1044 *(int *)data = fval; 1045 #endif 1046 return rv; 1047 } 1048 1049 /* 1050 * NOTE NOTE NOTE: 1051 * All tables (dac_calibrate_t) passed to the ioctl() have size > 1 1052 * and the index is always within this range. 1053 */ 1054 STATIC int 1055 ltc388x_ioctl(int unit, int devno, int opcode, void* data, int len) 1056 { 1057 int rv = SOC_E_NONE; 1058 #ifdef COMPILER_HAS_DOUBLE 1059 double fval=0, fval1=0; 1060 #else 1061 int fval=0, fval1=0; 1062 #endif 1063 int uV,ch,i; 1064 int iter; 1065 uint16 dac,time_ms; 1066 unsigned short voltage; 1067 uint32 datalen; 1068 dac_calibrate_t* params = NULL; 1069 i2c_device_t *dev = soc_i2c_device(unit, devno); 1070 int max_vs_config = MAX_VS_CONFIG; 1071 1072 #if defined(BCM_SABER2_SUPPORT) 1073 if(SOC_IS_SABER2(unit)) { 1074 max_vs_config = sizeof(sense_resistor_config_56260)/sizeof(i2c_ltc_t); 1075 } 1076 #endif 1077 #if defined(BCM_APACHE_SUPPORT) 1078 if (SOC_CONTROL(unit)->board_type == 0x94) { 1079 max_vs_config = sizeof(sense_resistor_config_56760)/sizeof(i2c_ltc_t); 1080 } else if (SOC_CONTROL(unit)->board_type == 0x96) { 1081 max_vs_config = sizeof(sense_resistor_config_56565)/sizeof(i2c_ltc_t); 1082 } 1083 #endif 1084 1085 #if defined(BCM_MONTEREY_SUPPORT) 1086 if (SOC_CONTROL(unit)->board_type == 0xAA) { 1087 max_vs_config = sizeof(sense_resistor_config_56670)/sizeof(i2c_ltc_t); 1088 } 1089 #endif 1090 #if defined(BCM_HELIX5_SUPPORT) 1091 if ((SOC_CONTROL(unit)->board_type == 0xB0) || (SOC_CONTROL(unit)->board_type == 0xB3) || 1092 (SOC_CONTROL(unit)->board_type == 0xB6)) { 1093 max_vs_config = sizeof(sense_resistor_config_56370)/sizeof(i2c_ltc_t); 1094 } 1095 #endif 1096 /* for HR3 boards */ 1097 if ((SOC_CONTROL(unit)->board_type == 0x8F) || 1098 (SOC_CONTROL(unit)->board_type == 0x90) || 1099 (SOC_CONTROL(unit)->board_type == 0x91)) { 1100 max_vs_config = sizeof(sense_resistor_config_56160)/sizeof(i2c_ltc_t); 1101 } 1102 1103 /* for GH2 boards */ 1104 if ((SOC_CONTROL(unit)->board_type == 0xA0) || 1105 (SOC_CONTROL(unit)->board_type == 0xA1)) { 1106 max_vs_config = sizeof(sense_resistor_config_56160)/sizeof(i2c_ltc_t); 1107 } 1108 1109 /* for WH2 boards */ 1110 if ((SOC_CONTROL(unit)->board_type == 0xA8) || 1111 (SOC_CONTROL(unit)->board_type == 0xA9)) { 1112 max_vs_config = sizeof(sense_resistor_config_53547)/sizeof(i2c_ltc_t); 1113 } 1114 1115 DEV_PRIVDATA_CHECK_RETURN(dev); 1116 1117 /* length field is actually used as an index into the dac_params table*/ 1118 if( !data || ( (DEV_DAC_PARAMS(dev) != NULL) && 1119 ((len > DEV_DAC_PARAM_LEN(dev)) && (len != I2C_BOTH_CH)))) { 1120 /* 1121 * len for op = I2C_LTC_IOC_SET_RCONFIG is used as table offset 1122 * instead of dac_param's length. 1123 */ 1124 if (opcode != I2C_LTC_IOC_SET_RCONFIG) { 1125 return SOC_E_PARAM; 1126 } 1127 } 1128 1129 /* Using mutex lock to ensure thread-safe for ioctl operations */ 1130 sal_mutex_take(DEV_MUTEX(dev), sal_mutex_FOREVER); 1131 1132 switch ( opcode ){ 1133 case I2C_ADC_QUERY_CHANNEL: 1134 ch = len; 1135 rv = ltc388x_get_ch_voltage(unit, devno, ch, &voltage); 1136 fval = voltage; 1137 #ifdef COMPILER_HAS_DOUBLE 1138 fval = L16_TO_V(fval); 1139 #else 1140 fval = L16_TO_UV(fval); 1141 #endif 1142 ((i2c_adc_t*)data)->max = 1143 ((i2c_adc_t*)data)->min = 1144 ((i2c_adc_t*)data)->val = fval; 1145 ((i2c_adc_t*)data)->delta = 0; 1146 ((i2c_adc_t*)data)->nsamples = 1; 1147 break; 1148 1149 /* Upload calibration table */ 1150 case I2C_DAC_IOC_SET_CALTAB: 1151 params = (dac_calibrate_t*)data; 1152 /* dac_params initialised */ 1153 DEV_DAC_PARAMS(dev) = params; 1154 DEV_DAC_PARAM_LEN(dev) = len; 1155 break; 1156 1157 case I2C_DAC_IOC_SETDAC_MIN: 1158 /* Set MIN voltage */ 1159 if (DEV_DAC_PARAMS(dev)) { 1160 rv = ltc388x_dac_set_ch_voltage(unit, devno, len, 1161 DEV_DAC_PARAMS(dev)[len].dac_min_hwval); 1162 } 1163 break; 1164 1165 case I2C_DAC_IOC_SETDAC_MAX: 1166 /* Set MAX voltage */ 1167 if (DEV_DAC_PARAMS(dev)) { 1168 rv = ltc388x_dac_set_ch_voltage(unit, devno, len, 1169 DEV_DAC_PARAMS(dev)[len].dac_max_hwval); 1170 } 1171 break; 1172 1173 case I2C_DAC_IOC_SETDAC_MID: 1174 /* Set mid-range voltage */ 1175 if (DEV_DAC_PARAMS(dev)) { 1176 rv = ltc388x_dac_set_ch_voltage(unit, devno, len, 1177 DEV_DAC_PARAMS(dev)[len].dac_mid_hwval); 1178 } 1179 break; 1180 1181 case I2C_DAC_IOC_CALIBRATE_MAX: 1182 /* Set MAX output value (from ADC) */ 1183 if (DEV_DAC_PARAMS(dev)) { 1184 #ifdef COMPILER_HAS_DOUBLE 1185 fval = *((double*)data); 1186 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1187 "CALIBRATE_MAX setting %f\n"), fval)); 1188 #else 1189 fval = *((int *)data); 1190 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1191 "CALIBRATE_MAX setting %d\n"), fval)); 1192 #endif 1193 DEV_DAC_PARAMS(dev)[len].max = fval; 1194 } 1195 break; 1196 1197 case I2C_DAC_IOC_CALIBRATE_MIN: 1198 /* Set MIN output value (from ADC) */ 1199 if (DEV_DAC_PARAMS(dev)) { 1200 #ifdef COMPILER_HAS_DOUBLE 1201 fval = *((double*)data); 1202 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1203 "CALIBRATE_MIN setting %f\n"), fval)); 1204 #else 1205 fval = *((int *)data); 1206 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1207 "CALIBRATE_MIN setting %d\n"), fval)); 1208 #endif 1209 DEV_DAC_PARAMS(dev)[len].min = fval; 1210 } 1211 break; 1212 1213 case I2C_DAC_IOC_CALIBRATE_STEP: 1214 /* Calibrate stepsize */ 1215 if (DEV_DAC_PARAMS(dev)) { 1216 DEV_DAC_PARAMS(dev)[len].step = 1217 (DEV_DAC_PARAMS(dev)[len].use_max ? -1 : 1) * 1218 (DEV_DAC_PARAMS(dev)[len].max - DEV_DAC_PARAMS(dev)[len].min) / 1219 (DEV_DAC_PARAMS(dev)[len].dac_max_hwval - 1220 DEV_DAC_PARAMS(dev)[len].dac_min_hwval); 1221 #ifdef COMPILER_HAS_DOUBLE 1222 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1223 "unit %d i2c %s: LTC388X calibration on function %s:" 1224 "(max=%f,min=%f,step=%f)\n"), 1225 unit, soc_i2c_devname(unit,devno), 1226 DEV_DAC_PARAMS(dev)[len].name, 1227 DEV_DAC_PARAMS(dev)[len].max, 1228 DEV_DAC_PARAMS(dev)[len].min, 1229 DEV_DAC_PARAMS(dev)[len].step)); 1230 #else 1231 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1232 "unit %d i2c %s: LTC388X calibration on function %s:" 1233 "(max=%d,min=%d,step=%d)\n"), 1234 unit, soc_i2c_devname(unit,devno), 1235 DEV_DAC_PARAMS(dev)[len].name, 1236 DEV_DAC_PARAMS(dev)[len].max, 1237 DEV_DAC_PARAMS(dev)[len].min, 1238 DEV_DAC_PARAMS(dev)[len].step)); 1239 #endif 1240 } 1241 break; 1242 case I2C_DAC_IOC_SET_VOUT: 1243 /* Set output voltage */ 1244 if (DEV_DAC_PARAMS(dev)) { 1245 #ifdef COMPILER_HAS_DOUBLE 1246 fval = *((double*)data); /* in V */ 1247 voltage = V_TO_L16(fval); 1248 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1249 "unit %d i2c %s: LTC388x ioctl I2C_DAC_IOC_SET_VOUT: " 1250 "voltage = %d, len = %d\n"), 1251 unit, soc_i2c_devname(unit,devno), voltage, len)); 1252 #else 1253 fval = *((int *)data); /* in uV */ 1254 voltage = UV_TO_L16(fval); 1255 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1256 "unit %d i2c %s: LTC388X ioctl I2C_DAC_IOC_SET_VOUT: " 1257 "voltage = %d, len = %d\n"), 1258 unit, soc_i2c_devname(unit,devno), voltage, len)); 1259 #endif 1260 if ((voltage > DEV_DAC_PARAMS(dev)[len].dac_max_hwval) || 1261 (voltage < DEV_DAC_PARAMS(dev)[len].dac_min_hwval)) { 1262 LOG_ERROR(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1263 "unit %d i2c %d: LTC388X given voltage %d " 1264 "beyond range for ch %d, %d, %d\n"), 1265 unit, devno, voltage, len, 1266 DEV_DAC_PARAMS(dev)[len].dac_max_hwval, 1267 DEV_DAC_PARAMS(dev)[len].dac_min_hwval)); 1268 rv=SOC_E_PARAM; 1269 break; 1270 } 1271 if ((rv=ltc388x_check_page(unit, devno, len)) < 0) { 1272 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1273 "unit: %d LTC388X device name: %s.\n"), 1274 len, unit, soc_i2c_devname(unit, devno))); 1275 } 1276 rv = ltc388x_dac_set_ch_voltage(unit, devno, len, voltage); 1277 } 1278 break; 1279 1280 case I2C_REGULATOR_IOC_VOLT_GET: 1281 rv = ltc388x_get_ch_voltage(unit, devno, len, &voltage); 1282 if (rv == SOC_E_NONE) { 1283 *((int *)data) = L16_TO_UV(voltage); 1284 } 1285 break; 1286 1287 case I2C_REGULATOR_IOC_VOLT_SET: 1288 uV = *(int *)data; 1289 voltage = UV_TO_L16(uV); 1290 rv = ltc388x_set_ch_voltage(unit, devno, len, voltage); 1291 break; 1292 1293 case I2C_LTC_IOC_SET_CONFIG: 1294 /* Initialising sense resistor */ 1295 #ifdef COMPILER_HAS_DOUBLE 1296 i = *(double *)data; 1297 #else 1298 i = *(int *)data; 1299 #endif 1300 #ifdef BCM_APACHE_SUPPORT 1301 if (SOC_CONTROL(unit)->board_type == 0x94) { 1302 /* Initializing with Apache/Maverick chip resistor configuration */ 1303 sense_resistor_config = sense_resistor_config_56760; 1304 rv = ltc388x_setmin_max(unit, devno, len); 1305 break; 1306 } else if (SOC_CONTROL(unit)->board_type == 0x96) { 1307 /* Initializing with FB5 chip resistor configuration */ 1308 sense_resistor_config = sense_resistor_config_56565; 1309 rv = ltc388x_setmin_max(unit, devno, len); 1310 break; 1311 } 1312 #endif 1313 1314 #ifdef BCM_MONTEREY_SUPPORT 1315 if (SOC_CONTROL(unit)->board_type == 0xAA) { 1316 /* Initializing with MONTEREY chip resistor configuration */ 1317 sense_resistor_config = sense_resistor_config_56670; 1318 rv = ltc388x_setmin_max(unit, devno, len); 1319 break; 1320 } 1321 #endif 1322 1323 #ifdef BCM_HELIX5_SUPPORT 1324 if ((SOC_CONTROL(unit)->board_type == 0xB0) || (SOC_CONTROL(unit)->board_type == 0xB3) || 1325 (SOC_CONTROL(unit)->board_type == 0xB6)) { 1326 /* Initializing with MONTEREY chip resistor configuration */ 1327 sense_resistor_config = sense_resistor_config_56370; 1328 rv = ltc388x_setmin_max(unit, devno, len); 1329 break; 1330 } 1331 #endif 1332 /* 1333 * Initializing with Tomahawk chip resistor configuration 1334 * 1335 * "i" is retrieved from incoming parameter and it is referenced as 1336 * board_type offset index. (offset from TH's board type) 1337 * 1338 * ltc388x_board_resistor_match() as the general matching process 1339 * uses this offset index to retreive the board 1340 * based sense_resistor_configuration. 1341 */ 1342 if (ltc388x_board_resistor_match(unit, i) == SOC_E_NOT_FOUND) { 1343 if (i != 4) { 1344 LOG_CLI((BSL_META_U(unit, "Error: Invalid chip: %d for " 1345 "LTC388X device %s .\n"), 1346 i, soc_i2c_devname(unit, devno))); 1347 rv=SOC_E_NOT_FOUND; 1348 break; 1349 } 1350 } 1351 if (DEV_DAC_PARAMS(dev)) { 1352 /* Setting max and min values for dac */ 1353 rv= ltc388x_setmin_max(unit, devno, len); 1354 } 1355 break; 1356 case I2C_LTC_IOC_SET_RCONFIG: 1357 i = len; 1358 1359 /* 1360 * Initializing with Tomahawk chip resistor configuration 1361 * 1362 * "i" is retrieved from incoming parameter and it is referenced as 1363 * board_type offset index. (offset from TH's board type) 1364 * 1365 * ltc388x_board_resistor_match() as the general matching process 1366 * uses this offset index to retreive the board 1367 * based sense_resistor_configuration. 1368 */ 1369 if (ltc388x_board_resistor_match(unit, i) == SOC_E_NOT_FOUND) { 1370 if (i != 4) { 1371 LOG_CLI((BSL_META_U(unit, "Error: Invalid chip: %d for " 1372 "LTC388X device %s .\n"), 1373 i, soc_i2c_devname(unit, devno))); 1374 rv=SOC_E_NOT_FOUND; 1375 break; 1376 } 1377 } 1378 break; 1379 case I2C_LTC_IOC_NOMINAL: 1380 if ((rv=ltc388x_wait_for_not_busy(unit, devno)) < 0) { 1381 LOG_CLI((BSL_META_U(unit, "Error: unit: %d LTC388X device name" 1382 " %s Device is busy.\n"), 1383 unit, soc_i2c_devname(unit, devno))); 1384 break; 1385 } 1386 ch=*((int *)data); 1387 if ((rv=ltc388x_check_page(unit, devno, ch)) < 0) { 1388 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1389 "unit: %d LTC388X device name: %s.\n"), 1390 ch, unit, soc_i2c_devname(unit, devno))); 1391 break; 1392 } 1393 if (DEV_DAC_PARAMS(dev)) { 1394 dac= (uint16) DEV_DAC_PARAMS(dev)[len].dac_mid_hwval; 1395 rv = ltc388x_write(unit, devno, PMBUS_CMD_VOUT_COMMAND,( 1396 void *)&dac, 2); 1397 /* Keep last value since DAC is write-only device */ 1398 DEV_DAC_PARAMS(dev)[len].dac_last_val = dac; 1399 } 1400 break; 1401 1402 case I2C_LTC_IOC_READ_VOUT: 1403 ch = len; 1404 ((i2c_adc_t*)data)->max = 1405 ((i2c_adc_t*)data)->min = 1406 ((i2c_adc_t*)data)->val = 1407 ((i2c_adc_t*)data)->delta = 0; 1408 1409 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) 1410 if ((SOC_CONTROL(unit)->board_type == 0x94) || 1411 (SOC_CONTROL(unit)->board_type == 0x96) || 1412 (SOC_CONTROL(unit)->board_type == 0xB0) || 1413 (SOC_CONTROL(unit)->board_type == 0xB3) || 1414 (SOC_CONTROL(unit)->board_type == 0xB6)) { 1415 ((i2c_adc_t*)data)->nsamples = 100; 1416 } else 1417 #endif /* #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) */ 1418 { 1419 ((i2c_adc_t*)data)->nsamples = 1; 1420 } 1421 1422 /* Taking Samples */ 1423 for (iter = 0; iter < ((i2c_adc_t*)data)->nsamples; iter++) { 1424 if ((rv = ltc388x_check_page(unit, devno, ch)) < 0) { 1425 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1426 "unit: %d LTC388X Device name: %s.\n"), 1427 ch, unit, soc_i2c_devname(unit, devno))); 1428 break; 1429 } 1430 datalen = 2; 1431 if ((rv = ltc388x_read(unit, devno, PMBUS_CMD_READ_VOUT, 1432 (void *)&voltage, &datalen)) < 0) { 1433 LOG_CLI((BSL_META_U(unit, "Error: Failed to read voltage in " 1434 "unit:%d LTC388x Device name:%s.\n"), 1435 unit, soc_i2c_devname(unit, devno))); 1436 break; 1437 } 1438 fval = voltage; 1439 #ifdef COMPILER_HAS_DOUBLE 1440 fval = L16_TO_V(fval); 1441 #else 1442 fval = L16_TO_UV(fval); 1443 #endif 1444 if (((i2c_adc_t*)data)->min == 0) { 1445 ((i2c_adc_t*)data)->min = fval; 1446 } 1447 if (fval > ((i2c_adc_t*)data)->max) { 1448 ((i2c_adc_t*)data)->max = fval; 1449 } else if (fval < ((i2c_adc_t*)data)->min) { 1450 ((i2c_adc_t*)data)->min = fval; 1451 } 1452 } 1453 ((i2c_adc_t*)data)->val = 1454 (((i2c_adc_t*)data)->max + ((i2c_adc_t*)data)->min) / 2; 1455 ((i2c_adc_t*)data)->delta = 1456 (((i2c_adc_t*)data)->max - ((i2c_adc_t*)data)->min); 1457 break; 1458 1459 case I2C_LTC_IOC_READ_IOUT: 1460 #ifdef COMPILER_HAS_DOUBLE 1461 i = *(double *)data; 1462 #else 1463 i = *(int *)data; 1464 #endif 1465 #if defined BCM_APACHE_SUPPORT || defined BCM_HELIX5_SUPPORT 1466 ((i2c_adc_t*)data)->max = 1467 ((i2c_adc_t*)data)->min = 1468 ((i2c_adc_t*)data)->val = 1469 ((i2c_adc_t*)data)->delta = 0; 1470 /* For Apache/Maverick/FB5/HX5 Three phase support */ 1471 if ((SOC_CONTROL(unit)->board_type == 0x94) || 1472 (SOC_CONTROL(unit)->board_type == 0x96) || 1473 (SOC_CONTROL(unit)->board_type == 0xAA) || 1474 (SOC_CONTROL(unit)->board_type == 0xB0) || 1475 (SOC_CONTROL(unit)->board_type == 0xB3) || 1476 (SOC_CONTROL(unit)->board_type == 0xB6)) { 1477 #if defined BCM_APACHE_SUPPORT 1478 if (SOC_CONTROL(unit)->board_type == 0x94) { 1479 /* Initializing with Apache/Maverick sense resistor configuration */ 1480 sense_resistor_config = sense_resistor_config_56760; 1481 } else if (SOC_CONTROL(unit)->board_type == 0x96) { 1482 /* Initializing with FB5 sense resistor configuration */ 1483 sense_resistor_config = sense_resistor_config_56565; 1484 } 1485 #endif 1486 #ifdef BCM_MONTEREY_SUPPORT 1487 if (SOC_CONTROL(unit)->board_type == 0xAA) { 1488 /* Initializing with MONTEREY chip resistor configuration */ 1489 sense_resistor_config = sense_resistor_config_56670; 1490 } 1491 #endif 1492 #ifdef BCM_HELIX5_SUPPORT 1493 if ((SOC_CONTROL(unit)->board_type == 0xB0) || 1494 (SOC_CONTROL(unit)->board_type == 0xB3) || 1495 (SOC_CONTROL(unit)->board_type == 0xB6)) { 1496 /* Initializing with MONTEREY chip resistor configuration */ 1497 sense_resistor_config = sense_resistor_config_56370; 1498 } 1499 #endif 1500 /* Taking 100 Samples */ 1501 for (iter = 0; iter < 100; iter++) { 1502 if (soc_i2c_addr(unit, devno) == I2C_LTC3884_SADDR42 && 1503 (SOC_CONTROL(unit)->board_type != 0xAA)) { 1504 SOC_IF_ERROR_RETURN 1505 (ltc388x_read_current(unit, devno, &fval, len)); 1506 rv = ltc388x_read_current(unit, devno + 1, &fval1, I2C_LTC3880_CH0); 1507 fval += fval1; 1508 } else { 1509 rv = ltc388x_read_current(unit, devno, &fval, len); 1510 } 1511 if (((i2c_adc_t*)data)->min == 0) { 1512 ((i2c_adc_t*)data)->min = fval; 1513 } 1514 if (fval > ((i2c_adc_t*)data)->max) { 1515 ((i2c_adc_t*)data)->max = fval; 1516 } else if (fval < ((i2c_adc_t*)data)->min) { 1517 ((i2c_adc_t*)data)->min = fval; 1518 } 1519 } 1520 ((i2c_adc_t*)data)->val = 1521 (((i2c_adc_t*)data)->max + ((i2c_adc_t*)data)->min) / 2; 1522 ((i2c_adc_t*)data)->delta = 1523 (((i2c_adc_t*)data)->max - ((i2c_adc_t*)data)->min); 1524 ((i2c_adc_t*)data)->nsamples = 100; 1525 break; 1526 } 1527 #endif /* #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) */ 1528 1529 if (ltc388x_board_resistor_match(unit, i) == SOC_E_NOT_FOUND) { 1530 if (i != 4) { 1531 LOG_CLI((BSL_META_U(unit, "Error: Invalid chip: %d for " 1532 "LTC388X device %s .\n"), 1533 i, soc_i2c_devname(unit, devno))); 1534 rv=SOC_E_NOT_FOUND; 1535 break; 1536 } 1537 } 1538 1539 rv=ltc388x_read_current(unit, devno, &fval, len); 1540 1541 /* For Tomahawk PVT Six phase support */ 1542 if ((SOC_CONTROL(unit)->board_type == 0x88) 1543 && (soc_i2c_devtype(unit, devno) == LTC3882_DEVICE_TYPE)) { 1544 rv=ltc388x_read_current(unit, devno+1, &fval1, I2C_BOTH_CH); 1545 fval += fval1; 1546 fval1 = 0; 1547 rv=ltc388x_read_current(unit, devno+2, &fval1, I2C_BOTH_CH); 1548 fval += fval1; 1549 } 1550 1551 #ifdef COMPILER_HAS_DOUBLE 1552 *(double *)data=fval; 1553 #else 1554 *(int *)data=fval; 1555 #endif 1556 break; 1557 1558 case I2C_LTC_IOC_READ_POUT: 1559 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) 1560 ((i2c_adc_t*)data)->max = 1561 ((i2c_adc_t*)data)->min = 1562 ((i2c_adc_t*)data)->val = 1563 ((i2c_adc_t*)data)->delta = 0; 1564 /* For Apache/Maverick/FB5/HX5 Three phase support */ 1565 if ((SOC_CONTROL(unit)->board_type == 0x94) || 1566 (SOC_CONTROL(unit)->board_type == 0x96) || 1567 (SOC_CONTROL(unit)->board_type == 0xAA) || 1568 (SOC_CONTROL(unit)->board_type == 0xB0) || 1569 (SOC_CONTROL(unit)->board_type == 0xB3) || 1570 (SOC_CONTROL(unit)->board_type == 0xB6)) { 1571 /* Taking 100 Samples */ 1572 for (iter = 0; iter < 100; iter++) { 1573 if (soc_i2c_addr(unit, devno) == I2C_LTC3884_SADDR42 && 1574 (SOC_CONTROL(unit)->board_type != 0xAA)) { 1575 SOC_IF_ERROR_RETURN 1576 (ltc388x_read_power(unit, devno, &fval, len)); 1577 rv = ltc388x_read_power(unit, devno + 1, &fval1, I2C_LTC3880_CH0); 1578 fval += fval1; 1579 } else { 1580 rv = ltc388x_read_power(unit, devno, &fval, len); 1581 } 1582 if (((i2c_adc_t*)data)->min == 0) { 1583 ((i2c_adc_t*)data)->min = fval; 1584 } 1585 if (fval > ((i2c_adc_t*)data)->max) { 1586 ((i2c_adc_t*)data)->max = fval; 1587 } else if (fval < ((i2c_adc_t*)data)->min) { 1588 ((i2c_adc_t*)data)->min = fval; 1589 } 1590 } 1591 ((i2c_adc_t*)data)->val = 1592 (((i2c_adc_t*)data)->max + ((i2c_adc_t*)data)->min) / 2; 1593 ((i2c_adc_t*)data)->delta = 1594 (((i2c_adc_t*)data)->max - ((i2c_adc_t*)data)->min); 1595 ((i2c_adc_t*)data)->nsamples = 100; 1596 break; 1597 } 1598 #endif /* #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) */ 1599 1600 rv=ltc388x_read_power(unit, devno, &fval, len); 1601 1602 /* For Tomahawk PVT Six phase support */ 1603 if ((SOC_CONTROL(unit)->board_type == 0x88) 1604 && (soc_i2c_devtype(unit, devno) == LTC3882_DEVICE_TYPE)) { 1605 rv=ltc388x_read_power(unit, devno+1, &fval1, I2C_BOTH_CH); 1606 fval += fval1; 1607 fval1 = 0; 1608 rv=ltc388x_read_power(unit, devno+2, &fval1, I2C_BOTH_CH); 1609 fval += fval1; 1610 } 1611 #ifdef COMPILER_HAS_DOUBLE 1612 *(double *)data=fval; 1613 #else 1614 *(int *)data=fval; 1615 #endif 1616 break; 1617 1618 case I2C_LTC_IOC_SET_VOUT: 1619 /* Finding and setting page numbers */ 1620 if (DEV_DAC_PARAMS(dev)) { 1621 for(i=0;i<max_vs_config;i++) { 1622 if(sal_strcmp(DEV_DAC_PARAMS(dev)[len].name, 1623 sense_resistor_config[i].function) == 0 ) { 1624 break; 1625 } 1626 } 1627 if (i == max_vs_config) { 1628 LOG_CLI((BSL_META_U(unit, "Error: failed to find page number" 1629 " for VDD_%s in sense resistor table.\n"), 1630 DEV_DAC_PARAMS(dev)[len].name)); 1631 rv=SOC_E_NOT_FOUND; 1632 break; 1633 } 1634 ch = sense_resistor_config[i].ch; 1635 if ((rv=ltc388x_check_page(unit, devno, ch)) < 0) { 1636 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1637 "LTC388X device.\n"), ch)); 1638 break; 1639 } 1640 /* Conversion of output voltage */ 1641 #ifdef COMPILER_HAS_DOUBLE 1642 fval = *((double*)data); 1643 voltage = (fval*4096); 1644 #else 1645 fval = *((int*)data); 1646 /*2^12 conversion and changing from uVolt */ 1647 voltage = (fval*4096)/1000000; 1648 #endif 1649 if ((voltage < DEV_DAC_PARAMS(dev)[len].dac_min_hwval)|| 1650 (voltage > DEV_DAC_PARAMS(dev)[len].dac_max_hwval)) { 1651 #ifdef COMPILER_HAS_DOUBLE 1652 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1653 "unit %d i2c %d: LTC388X given voltage %2.3f V " 1654 "beyond range( max=%2.3f V, min=%2.3f V) for " 1655 "voltage VDD_%s \n"), unit, devno, 1656 (double)voltage/4096, 1657 (double) DEV_DAC_PARAMS(dev)[len].dac_max_hwval/4096, 1658 (double) DEV_DAC_PARAMS(dev)[len].dac_min_hwval/4096, 1659 DEV_DAC_PARAMS(dev)[len].name)); 1660 #else 1661 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1662 "unit %d i2c %d: LTC388X given voltage %d mV " 1663 "beyond range( max=%d mV, min=%d mV ) for " 1664 "voltage VDD_%s \n"), unit, devno, 1665 voltage*1000/4096, 1666 DEV_DAC_PARAMS(dev)[len].dac_max_hwval*1000/4096, 1667 DEV_DAC_PARAMS(dev)[len].dac_min_hwval*1000/4096, 1668 DEV_DAC_PARAMS(dev)[len].name)); 1669 1670 #endif 1671 rv = SOC_E_PARAM; 1672 break; 1673 } 1674 dac = voltage; 1675 /* Show what we are doing, for now ... */ 1676 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1677 "unit %d i2c %s: LTC388X ioctl " 1678 "I2C_DAC_IOC_SET_VOUT : voltage = %d, len = %d\n"), 1679 unit, soc_i2c_devname(unit,devno), voltage, len)); 1680 #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) 1681 /* For Apache/Maverick/FB5/HX5 Three Phase Support 1682 * LTC3884 at 0x42 : Channel 0,1 = VDD_Core 1683 * LTC3884 at 0x43 : Channel 0 = VDD_Core 1684 * Channel 1 = VDD_Analog 1685 */ 1686 if ((SOC_CONTROL(unit)->board_type == 0x94) || 1687 (SOC_CONTROL(unit)->board_type == 0x96) || 1688 (SOC_CONTROL(unit)->board_type == 0xB0) || 1689 (SOC_CONTROL(unit)->board_type == 0xB3) || 1690 (SOC_CONTROL(unit)->board_type == 0xB6)) { 1691 if (soc_i2c_addr(unit, devno) == I2C_LTC3884_SADDR42) { 1692 SOC_IF_ERROR_RETURN 1693 (ltc388x_dac_set_ch_voltage(unit, devno, ch, voltage)); 1694 /* Set VDD_Core on Channel 0 of I2C_LTC3884_SADDR43 */ 1695 SOC_IF_ERROR_RETURN 1696 (ltc388x_dac_set_ch_voltage(unit, devno + 1, I2C_LTC3880_CH0, voltage)); 1697 } else { 1698 SOC_IF_ERROR_RETURN 1699 (ltc388x_dac_set_ch_voltage(unit, devno, ch, voltage)); 1700 } 1701 /* Store voltage setting in NV memory to retain them after power cycling */ 1702 rv = ltc388x_write(unit, devno, PMBUS_CMD_STORE_USER_ALL, (void *)&dac, 0); 1703 } else 1704 #endif /* #if defined (BCM_APACHE_SUPPORT) || defined (BCM_HELIX5_SUPPORT) */ 1705 { 1706 rv = ltc388x_write(unit, devno, PMBUS_CMD_VOUT_COMMAND,(void *) &dac, 2); 1707 } 1708 /* Keep last value since DAC is write-only device */ 1709 DEV_DAC_PARAMS(dev)[len].dac_last_val = dac; 1710 } 1711 break; 1712 1713 case I2C_SET_SEQ: 1714 if ((rv = ltc388x_check_page(unit, devno, len)) < 0) { 1715 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1716 "unit: %d LTC388X device name: %s.\n"), 1717 len, unit, soc_i2c_devname(unit, devno))); 1718 break; 1719 } 1720 #ifdef COMPILER_HAS_DOUBLE 1721 fval = *((double*)data); 1722 rv = ltc388x_float_to_L11(fval, &time_ms); 1723 #else 1724 fval = *((int*)data); 1725 rv = ltc388x_float_to_L11(fval/1000000, &time_ms); 1726 #endif 1727 if ((rv = ltc388x_write(unit, devno, PMBUS_CMD_POWER_ON_DELAY, 1728 (void *) &time_ms, 2)) < 0) { 1729 LOG_CLI((BSL_META_U(unit, "Error: failed to set TON_DELAY for" 1730 " %s.\n"), soc_i2c_devname(unit, devno))); 1731 break; 1732 } 1733 if ((rv = ltc388x_wait_for_not_busy(unit, devno)) < 0) { 1734 LOG_CLI((BSL_META_U(unit, "Error: unit: %d LTC388X device name" 1735 " %s Device is busy.\n"), 1736 unit, soc_i2c_devname(unit, devno))); 1737 break; 1738 } 1739 dac = 0; 1740 if ((rv = ltc388x_write(unit, devno, PMBUS_CMD_STORE_USER_ALL, 1741 (void *)&dac, 0)) < 0) { 1742 LOG_CLI((BSL_META_U(unit, "Error: Failed to store the TON_DELAY" 1743 " value to NVRAM in device: %s.\n"), 1744 soc_i2c_devname(unit, devno))); 1745 break; 1746 } 1747 if ((rv = ltc388x_wait_for_not_busy(unit, devno)) < 0) { 1748 LOG_CLI((BSL_META_U(unit, "Error: unit: %d LTC388X device name" 1749 " %s Device is busy.\n"), 1750 unit, soc_i2c_devname(unit, devno))); 1751 break; 1752 } 1753 break; 1754 1755 case I2C_READ_SEQ: 1756 if ((rv = ltc388x_check_page(unit, devno, len)) < 0) { 1757 LOG_CLI((BSL_META_U(unit, "Error: failed to set page %d in " 1758 "unit: %d LTC388X device name: %s.\n"), 1759 len, unit, soc_i2c_devname(unit, devno))); 1760 break; 1761 } 1762 datalen = 2; 1763 if ((rv = ltc388x_read(unit, devno, PMBUS_CMD_POWER_ON_DELAY, 1764 (void *) &time_ms, &datalen)) < 0) { 1765 LOG_CLI((BSL_META_U(unit, "Error: failed to read TON_DELAY " 1766 "for %s.\n"), soc_i2c_devname(unit, devno))); 1767 break; 1768 } 1769 rv = ltc388x_L11_to_float(time_ms, &fval); 1770 #ifdef COMPILER_HAS_DOUBLE 1771 *(double *)data = fval; 1772 #else 1773 *(int *)data = (fval); 1774 #endif 1775 break; 1776 1777 default: 1778 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1779 "unit %d i2c %s: LTC388X_ioctl: invalid opcode (%d)\n"), 1780 unit, soc_i2c_devname(unit,devno), opcode)); 1781 break; 1782 } 1783 sal_mutex_give(DEV_MUTEX(dev)); 1784 return rv; 1785 } 1786 1787 STATIC int 1788 ltc388x_init(int unit, int devno, void* data, int len) 1789 { 1790 int rv = SOC_E_NONE; 1791 uint16 dac; 1792 i2c_device_t *dev = soc_i2c_device(unit, devno); 1793 char *devname; 1794 int devtype; 1795 1796 if (dev == NULL) { 1797 rv = SOC_E_INTERNAL; 1798 goto err_return; 1799 } 1800 1801 devname = (char *)soc_i2c_devname(unit, devno); 1802 if (dev->priv_data == NULL) { 1803 dev->priv_data = sal_alloc(sizeof(device_data_t), devname); 1804 if (dev->priv_data == NULL) { 1805 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1806 "Fail to allocate private data fo dev %s\n"), 1807 soc_i2c_devname(unit, devno))); 1808 rv = SOC_E_MEMORY; 1809 goto err_return; 1810 } 1811 DEV_MUTEX(dev) = sal_mutex_create(devname); 1812 if (DEV_MUTEX(dev) == NULL) { 1813 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1814 "Fail to create %s mutex lock\n"), 1815 soc_i2c_devname(unit, devno))); 1816 rv = SOC_E_MEMORY; 1817 goto err_free_mem; 1818 } 1819 DEV_DAC_PARAMS(dev) = NULL; 1820 DEV_DAC_PARAM_LEN(dev) = 0; 1821 } 1822 1823 sal_mutex_take(DEV_MUTEX(dev), sal_mutex_FOREVER); 1824 if ((rv=ltc388x_write(unit, devno, PMBUS_CMD_CLEAR_FAULTS, 1825 (void *)&dac, 0)) < 0) { 1826 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1827 "Error: Failed to clear fault for LTC388X Device name:%s.\n"), 1828 soc_i2c_devname(unit, devno))); 1829 goto err_unlock; 1830 } 1831 if ((rv=ltc388x_wait_for_not_busy(unit, devno)) < 0) { 1832 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1833 "Error: LTC388X device name %s Device is busy.\n"), 1834 soc_i2c_devname(unit, devno))); 1835 goto err_unlock; 1836 } 1837 sal_mutex_give(DEV_MUTEX(dev)); 1838 1839 devtype = soc_i2c_devtype(unit, devno); 1840 if (devtype == LTC3880_DEVICE_TYPE) { 1841 soc_i2c_devdesc_set(unit, devno, "Linear Tech LTC3880 Step_Down DC/DC " 1842 "Controller"); 1843 } else if (devtype == LTC3882_DEVICE_TYPE) { 1844 soc_i2c_devdesc_set(unit, devno, "Linear Tech LTC3882 Step_Down DC/DC " 1845 "Controller"); 1846 } else if (devtype == LTC3884_DEVICE_TYPE) { 1847 soc_i2c_devdesc_set(unit, devno, "Linear Tech LTC3884 Step_Down DC/DC " 1848 "Controller"); 1849 } else if (devtype == LTM4676_DEVICE_TYPE) { 1850 soc_i2c_devdesc_set(unit, devno, "Linear Tech LTM4676 Step_Down DC/DC " 1851 "Controller"); 1852 } else { 1853 soc_i2c_devdesc_set(unit, devno, devname); 1854 } 1855 1856 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1857 "ltc388x_init: %s, devNo=0x%x\n"), 1858 soc_i2c_devname(unit,devno), devno)); 1859 1860 return rv; 1861 1862 err_unlock: 1863 sal_mutex_give(DEV_MUTEX(dev)); 1864 sal_mutex_destroy(DEV_MUTEX(dev)); 1865 err_free_mem: 1866 sal_free(dev->priv_data); 1867 dev->priv_data = NULL; 1868 err_return: 1869 return rv; 1870 } 1871 1872 STATIC int 1873 ltc388x_deinit(int unit, int devno) 1874 { 1875 int rv = SOC_E_NONE; 1876 i2c_device_t *dev = soc_i2c_device(unit, devno); 1877 1878 if (dev != NULL) { 1879 if (dev->priv_data != NULL) { 1880 if (DEV_MUTEX(dev) != NULL) { 1881 sal_mutex_destroy(DEV_MUTEX(dev)); 1882 } 1883 sal_free(dev->priv_data); 1884 dev->priv_data = NULL; 1885 } 1886 } else { 1887 rv = SOC_E_INTERNAL; 1888 } 1889 1890 return rv; 1891 } 1892 1893 STATIC int 1894 ltc388x_check_device_id(int unit, int devno, char *id, char *model) 1895 { 1896 int rv = SOC_E_NONE; 1897 i2c_saddr_t saddr; 1898 uint8 block_size = 0; 1899 uint8 block_data[256+1]; 1900 1901 saddr = soc_i2c_addr(unit, devno); 1902 if (id != NULL) { 1903 rv = soc_i2c_block_read(unit, saddr, PMBUS_CMD_MFR_ID, 1904 &block_size, block_data); 1905 if (rv == SOC_E_NONE) { 1906 block_data[block_size] = '\0'; 1907 if (sal_strcmp((char *)block_data, id) != 0) { 1908 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1909 "I2C %s(0x%02x) MFR_ID(%d) is read " 1910 "as [%s], not the expected value [%s]\n"), 1911 soc_i2c_devname(unit, devno), saddr, 1912 block_size, block_data, id)); 1913 goto match_fail; 1914 } 1915 } 1916 else { 1917 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1918 "Fail to get MFR_ID for I2C device addr 0x%02x\n"), saddr)); 1919 goto match_fail; 1920 } 1921 } 1922 1923 if (model != NULL) { 1924 rv = soc_i2c_block_read(unit, saddr, PMBUS_CMD_MFR_MODEL, 1925 &block_size, block_data); 1926 if (rv == SOC_E_NONE) { 1927 block_data[block_size] = '\0'; 1928 if (sal_strcmp((char *)block_data, model) != 0) { 1929 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1930 "I2C %s(0x%02x) MFR_MODEL(%d) read " 1931 "as [%s], not the expected value [%s]\n"), 1932 soc_i2c_devname(unit, devno), saddr, 1933 block_size, block_data, model)); 1934 goto match_fail; 1935 } 1936 } 1937 else { 1938 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 1939 "Fail to get MFR_MODEL for I2C device addr 0x%02x\n"), saddr)); 1940 goto match_fail; 1941 } 1942 } 1943 1944 return rv; 1945 1946 match_fail: 1947 return SOC_E_NOT_FOUND; 1948 } 1949 1950 STATIC int 1951 ltc3880_init(int unit, int devno, void* data, int len) 1952 { 1953 SOC_IF_ERROR_RETURN( 1954 ltc388x_check_device_id(unit, devno, LTC_MFR_ID, LTC_3880_MFR_MODEL)); 1955 1956 return ltc388x_init(unit, devno, data, len); 1957 } 1958 1959 STATIC int 1960 ltc3882_init(int unit, int devno, void* data, int len) 1961 { 1962 SOC_IF_ERROR_RETURN( 1963 ltc388x_check_device_id(unit, devno, LTC_MFR_ID, LTC_3882_MFR_MODEL)); 1964 1965 return ltc388x_init(unit, devno, data, len); 1966 } 1967 1968 STATIC int 1969 ltc3884_init(int unit, int devno, void* data, int len) 1970 { 1971 SOC_IF_ERROR_RETURN( 1972 ltc388x_check_device_id(unit, devno, LTC_MFR_ID, LTC_3884_MFR_MODEL)); 1973 1974 return ltc388x_init(unit, devno, data, len); 1975 } 1976 1977 STATIC int 1978 ltm4676_init(int unit, int devno, void* data, int len) 1979 { 1980 SOC_IF_ERROR_RETURN( 1981 ltc388x_check_device_id(unit, devno, LTC_MFR_ID, LTM_4676_MFR_MODEL)); 1982 1983 return ltc388x_init(unit, devno, data, len); 1984 } 1985 1986 1987 /* ltc 3880 voltage control Chip Driver callout */ 1988 i2c_driver_t _soc_i2c_ltc3880_driver = { 1989 0x0, 0x0, /* System assigned bytes */ 1990 LTC3880_DEVICE_TYPE, 1991 ltc388x_read, 1992 ltc388x_write, 1993 ltc388x_ioctl, 1994 ltc3880_init, 1995 ltc388x_deinit, 1996 }; 1997 1998 /* ltc 3882 voltage control Chip Driver callout */ 1999 i2c_driver_t _soc_i2c_ltc3882_driver = { 2000 0x0, 0x0, /* System assigned bytes */ 2001 LTC3882_DEVICE_TYPE, 2002 ltc388x_read, 2003 ltc388x_write, 2004 ltc388x_ioctl, 2005 ltc3882_init, 2006 ltc388x_deinit, 2007 }; 2008 2009 /* ltc 3884 voltage control Chip Driver callout */ 2010 i2c_driver_t _soc_i2c_ltc3884_driver = { 2011 0x0, 0x0, /* System assigned bytes */ 2012 LTC3884_DEVICE_TYPE, 2013 ltc388x_read, 2014 ltc388x_write, 2015 ltc388x_ioctl, 2016 ltc3884_init, 2017 ltc388x_deinit, 2018 }; 2019 2020 /* ltm 4676 voltage control Chip Driver callout */ 2021 i2c_driver_t _soc_i2c_ltm4676_driver = { 2022 0x0, 0x0, /* System assigned bytes */ 2023 LTM4676_DEVICE_TYPE, 2024 ltc388x_read, 2025 ltc388x_write, 2026 ltc388x_ioctl, 2027 ltm4676_init, 2028 ltc388x_deinit, 2029 };