pmbus.c (17854B)
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 pmbus an integrated power control IC. 8 */ 9 10 #include <sal/types.h> 11 #include <soc/debug.h> 12 #include <soc/drv.h> 13 #include <soc/error.h> 14 #include <soc/i2c.h> 15 #include <shared/bsl.h> 16 #include <sal/appl/sal.h> 17 18 #ifdef COMPILER_HAS_DOUBLE 19 #define I2C_DATA_T double 20 #define I2C_DATA_F "f" 21 #else 22 #define I2C_DATA_T int 23 #define I2C_DATA_F "d" 24 #endif 25 26 #define POWER(exponent, input_val) \ 27 exponent < 0 ? \ 28 (int)((int) (input_val) << (exponent*(-1))): \ 29 (int)((int) (input_val*1000000) >> exponent)/1000000 30 31 typedef struct device_data_s { 32 sal_mutex_t lock; /* mutex lock for device operation */ 33 int pmbus_io_flags; /* pmbus io ctrl support flag */ 34 #define PMBUS_VID 0x20 35 int dac_vout_mode; /* vout_command mode */ 36 dac_calibrate_t *dac_params; /* dac params for each device channel */ 37 int dac_param_len; /* number of dac params, for multi-channel device */ 38 } device_data_t; 39 40 #define DEV_DAC_VOUTMODE(dev) \ 41 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->dac_vout_mode) 42 #define DEV_DAC_PARAMS(dev) \ 43 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->dac_params) 44 #define DEV_DAC_PARAM_LEN(dev) \ 45 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->dac_param_len) 46 47 #define DEV_CHECK_RETURN(dev) \ 48 { \ 49 if ((dev) == NULL) { \ 50 return SOC_E_INTERNAL; \ 51 } \ 52 } 53 54 #define DEV_PRIVDATA_CHECK_RETURN(dev) \ 55 { \ 56 DEV_CHECK_RETURN(dev) \ 57 if ((dev)->priv_data == NULL) { \ 58 return SOC_E_INTERNAL; \ 59 } \ 60 } 61 62 /* 63 * Convert a floating point value into a 64 * LinearFloat5_11 formatted word 65 */ 66 STATIC int 67 #ifdef COMPILER_HAS_DOUBLE 68 pmbus_float_to_L11(double input_val, uint16* data) 69 #else 70 pmbus_float_to_L11(int input_val, uint16* data) 71 #endif 72 { 73 uint16 uExponent, uMantissa; 74 /* set exponent to -16 */ 75 int16 exponent = -16; 76 /* extract mantissa from input value */ 77 int mantissa = POWER(exponent, input_val); 78 79 /* Search for an exponent that produces 80 * a valid 11-bit mantissa */ 81 do 82 { 83 if((mantissa >= -1024) && (mantissa <= +1023)) 84 { 85 break; /* stop if mantissa valid */ 86 } 87 exponent++; 88 mantissa = POWER(exponent, input_val); 89 } while (exponent < +15); 90 91 /* Format the exponent of the L11 */ 92 uExponent = exponent << 11; 93 /* Format the mantissa of the L11 */ 94 uMantissa = mantissa & 0x07FF; 95 /* Compute value as exponent | mantissa */ 96 *(data) = uExponent | uMantissa; 97 return SOC_E_NONE; 98 } 99 100 /* 101 * Convert a LinearFloat5_11 formatted word 102 * into a floating point value 103 */ 104 STATIC int 105 pmbus_L11_to_float(uint16 input_val, void *data) 106 { 107 /* extract exponent as MS 5 bits */ 108 int8 exponent = input_val >> 11; 109 /* extract mantissa as LS 11 bits */ 110 int16 mantissa = input_val & 0x7ff; 111 /* sign extend exponent from 5 to 8 bits */ 112 if( exponent > 0x0F ) exponent |= 0xE0; 113 /* sign extend mantissa from 11 to 16 bits */ 114 if( mantissa > 0x03FF ) mantissa |= 0xF800; 115 #ifdef COMPILER_HAS_DOUBLE 116 /* compute value as mantissa * 2^(exponent) */ 117 *(double *)data= exponent < 0 ? 118 (double) ((mantissa*1000000) >> 119 (exponent*(-1)))/1000000: 120 (double) (mantissa << exponent); 121 #else 122 *(int *)data= exponent < 0 ? 123 (((mantissa)*1000000) >> (exponent*(-1))): 124 ((mantissa) << exponent)*100000; 125 #endif 126 return SOC_E_NONE; 127 } 128 129 STATIC int 130 pmbus_read(int unit, int devno, uint16 addr, uint8* data, uint32* len) 131 { 132 133 int rv = SOC_E_NONE; 134 uint8 saddr = soc_i2c_addr(unit, devno); 135 136 if (!*len) { 137 return SOC_E_NONE; 138 } 139 140 /* reads a single byte from a device, from a designated register*/ 141 if (*len == 1) { 142 rv = soc_i2c_read_byte_data(unit, saddr, addr,data); 143 soc_i2c_device(unit, devno)->rbyte++; 144 } else if (*len == 2) { 145 rv = soc_i2c_read_word_data(unit, saddr, addr,(uint16 *)data); 146 soc_i2c_device(unit, devno)->rbyte +=2; 147 } else { 148 /* not supported for now */ 149 } 150 151 return rv; 152 } 153 154 STATIC int 155 pmbus_write(int unit, int devno, uint16 addr, uint8* data, uint32 len) 156 { 157 int rv = SOC_E_NONE; 158 uint8 saddr = soc_i2c_addr(unit, devno); 159 160 if (len == 0) { 161 /* simply writes command code to device */ 162 rv = soc_i2c_write_byte(unit, saddr, addr); 163 } else if (len == 1) { 164 rv = soc_i2c_write_byte_data(unit, saddr, addr,*data); 165 soc_i2c_device(unit, devno)->tbyte++; 166 } else if (len == 2) { 167 rv = soc_i2c_write_word_data(unit, saddr, addr, *(uint16 *)data); 168 soc_i2c_device(unit, devno)->tbyte += 2; 169 } 170 return rv; 171 } 172 173 STATIC int 174 pmbus_ioctl(int unit, int devno, int opcode, void* data, int len) 175 { 176 int rv = SOC_E_NONE; 177 I2C_DATA_T fval = 0,tmp; 178 uint8 data8; 179 uint16 dac; 180 uint16 time_ms; 181 uint32 datalen = 0; 182 dac_calibrate_t* dac_params = NULL; 183 i2c_device_t *dev = soc_i2c_device(unit, devno); 184 185 DEV_PRIVDATA_CHECK_RETURN(dev); 186 187 dac_params = DEV_DAC_PARAMS(dev); 188 /* length field is actually used as an index into the dac_params table*/ 189 if((!data) || ((dac_params != NULL) && (len > DEV_DAC_PARAM_LEN(dev)))) { 190 return SOC_E_PARAM; 191 } 192 193 switch (opcode){ 194 case PMBUS_IOC_SET_DAC: 195 /* Set special dac table */ 196 dac_params = (dac_calibrate_t*)data; 197 DEV_DAC_PARAMS(dev) = dac_params; 198 DEV_DAC_PARAM_LEN(dev) = len; 199 200 /* Set vout command mode*/ 201 datalen = 1; 202 if ((rv = pmbus_read(unit, devno, PMBUS_CMD_VOUT_MODE, 203 &data8, &datalen)) < 0) { 204 LOG_ERROR(BSL_LS_SOC_COMMON, 205 (BSL_META_U(unit, "Error: failed to read VOUT MODE for %s.\n"), 206 soc_i2c_devname(unit, devno))); 207 break; 208 } 209 DEV_DAC_VOUTMODE(dev) = data8; 210 break; 211 212 case PMBUS_IOC_SET_VOUT: 213 /* Set output voltage */ 214 fval = *((I2C_DATA_T*)data); 215 if (dac_params) { 216 if ((fval < dac_params[len].min)||(fval > dac_params[len].max)){ 217 LOG_VERBOSE(BSL_LS_SOC_COMMON, 218 (BSL_META_U(unit, 219 "unit %d i2c %s: calibration/range error :" 220 "requested=%"I2C_DATA_F" (max=%"I2C_DATA_F"," 221 "min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"), 222 unit, soc_i2c_devname(unit,devno), 223 fval, dac_params[len].max, 224 dac_params[len].min, 225 dac_params[len].step)); 226 return SOC_E_PARAM; 227 } 228 229 if (DEV_DAC_VOUTMODE(dev) & PMBUS_VID) { 230 /* VID mode */ 231 if(dac_params[len].use_max) { 232 tmp = ((dac_params[len].max - fval) / dac_params[len].step); 233 tmp = dac_params[len].dac_max_hwval - tmp; 234 } else { 235 tmp = ((dac_params[len].max - fval) / dac_params[len].step); 236 tmp = dac_params[len].dac_max_hwval + tmp; 237 } 238 dac = (uint8)tmp; 239 } else { 240 /* Linear mode */ 241 rv = pmbus_float_to_L11(fval, &dac); 242 } 243 244 /* Show what we are doing, for now ... */ 245 LOG_VERBOSE(BSL_LS_SOC_COMMON, 246 (BSL_META_U(unit, 247 "unit %d i2c %s: Set V_%s:" 248 "request=%"I2C_DATA_F" dac=0x%x (max=%"I2C_DATA_F"," 249 "min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"), 250 unit, soc_i2c_devname(unit, devno), 251 dac_params[len].name, 252 fval, 253 dac, 254 dac_params[len].max, 255 dac_params[len].min, 256 dac_params[len].step)); 257 if ((rv = pmbus_write(unit, devno, 258 PMBUS_CMD_VOUT_COMMAND, (uint8 *)&dac, 2)) < 0) { 259 LOG_ERROR(BSL_LS_SOC_COMMON, 260 (BSL_META_U(unit, "Error: failed to set VOUT for %s.\n"), 261 soc_i2c_devname(unit, devno))); 262 break; 263 } 264 /* Keep last value since DAC is write-only device */ 265 dac_params[len].dac_last_val = dac; 266 } 267 break; 268 269 case PMBUS_IOC_READ_VOUT: 270 /* Set output voltage */ 271 if (dac_params) { 272 datalen = 2; 273 if ((rv = pmbus_read(unit, devno, PMBUS_CMD_READ_VOUT, 274 (uint8 *)&dac, &datalen)) < 0) { 275 LOG_ERROR(BSL_LS_SOC_COMMON, 276 (BSL_META_U(unit, "Error: failed to read VOUT for %s.\n"), 277 soc_i2c_devname(unit, devno))); 278 break; 279 } 280 281 /* Show what we are doing, for now ... */ 282 LOG_VERBOSE(BSL_LS_SOC_COMMON, 283 (BSL_META_U(unit, 284 "unit %d i2c %s: Get V_%s:" 285 " dac=0x%x (max=%"I2C_DATA_F"," 286 "min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"), 287 unit, soc_i2c_devname(unit, devno), 288 dac_params[len].name, 289 dac, 290 dac_params[len].max, 291 dac_params[len].min, 292 dac_params[len].step)); 293 294 if (DEV_DAC_VOUTMODE(dev) & PMBUS_VID) { 295 if(dac_params[len].use_max) { 296 tmp = dac_params[len].dac_max_hwval - dac; 297 fval = dac_params[len].max - tmp * dac_params[len].step; 298 } else { 299 tmp = dac - dac_params[len].dac_max_hwval; 300 fval = dac_params[len].max - tmp * dac_params[len].step; 301 } 302 } else { 303 /* Linear mode */ 304 rv = pmbus_L11_to_float(dac, &fval); 305 } 306 } 307 *((I2C_DATA_T*)data) = fval; 308 break; 309 310 case PMBUS_IOC_SET_SEQ: 311 time_ms = *((uint16 *)data); 312 time_ms &= ((1 << 4) - 1); 313 if ((rv = pmbus_write(unit, devno, PMBUS_CMD_POWER_ON_DELAY, 314 (uint8 *)&time_ms, 2)) < 0) { 315 LOG_ERROR(BSL_LS_SOC_COMMON, 316 (BSL_META_U(unit, "Error: failed to set TON_DELAY for %s.\n"), 317 soc_i2c_devname(unit, devno))); 318 break; 319 } 320 break; 321 322 case PMBUS_IOC_READ_SEQ: 323 datalen = 2; 324 if ((rv = pmbus_read(unit, devno, PMBUS_CMD_POWER_ON_DELAY, 325 (uint8 *)&time_ms, &datalen)) < 0) { 326 LOG_ERROR(BSL_LS_SOC_COMMON, 327 (BSL_META_U(unit, "Error: failed to read TON_DELAY for %s.\n"), 328 soc_i2c_devname(unit, devno))); 329 break; 330 } 331 *((uint16 *)data) = time_ms; 332 break; 333 334 case PMBUS_IOC_READ_IOUT: 335 datalen = 2; 336 if ((rv = pmbus_read(unit, devno, PMBUS_CMD_READ_IOUT, 337 (uint8 *)&dac, &datalen)) < 0) { 338 LOG_ERROR(BSL_LS_SOC_COMMON, 339 (BSL_META_U(unit, "Error: failed to read current for %s.\n"), 340 soc_i2c_devname(unit, devno))); 341 break; 342 } 343 rv = pmbus_L11_to_float(dac, &fval); 344 #ifdef COMPILER_HAS_DOUBLE 345 *(double *)data=fval*1000; 346 #else 347 *(int *)data=fval; 348 #endif 349 break; 350 351 default: 352 LOG_VERBOSE(BSL_LS_SOC_COMMON, 353 (BSL_META_U(unit, 354 "unit %d i2c %s: pmbus_ioctl: invalid opcode (%d)\n"), 355 unit, soc_i2c_devname(unit, devno), opcode)); 356 break; 357 } 358 359 return rv; 360 } 361 362 /* Calibration table in effect */ 363 static dac_calibrate_t 364 ncp4200_dac_params = {0, "core", 365 NCP4200_MAX_VOL, NCP4200_MIN_VOL, NCP4200_DAC_STEP, 0, 366 NCP4200_MIN_DACVAL, NCP4200_MAX_DACVAL, NCP4200_MID_DACVAL, 0x0}; 367 368 static dac_calibrate_t 369 ncp81233_dac_params = {0, "core", 370 NCP81233_MAX_VOL, NCP81233_MIN_VOL, NCP81233_DAC_STEP, 0, 371 NCP81233_MAX_DACVAL, NCP81233_MIN_DACVAL, NCP81233_MID_DACVAL, 0x1}; 372 373 STATIC int 374 pmbus_init(int unit, int devno, void* data, int len) 375 { 376 uint8 data8, mfr_id; 377 uint16 mfr_model; 378 uint32 datalen = 0; 379 int rv = SOC_E_NONE, line = __LINE__; 380 i2c_device_t *dev = soc_i2c_device(unit, devno); 381 char *devname; 382 383 if (dev == NULL) { 384 return SOC_E_INTERNAL; 385 } 386 devname = (char *)soc_i2c_devname(unit, devno); 387 if (dev->priv_data == NULL) { 388 dev->priv_data = sal_alloc(sizeof(device_data_t), devname); 389 if (dev->priv_data == NULL) { 390 LOG_ERROR(BSL_LS_SOC_COMMON, 391 (BSL_META_U(unit, 392 "Fail to allocate private data fo dev %s\n"), 393 soc_i2c_devname(unit, devno))); 394 rv = SOC_E_MEMORY; 395 return rv; 396 } 397 DEV_DAC_PARAMS(dev) = NULL; 398 DEV_DAC_PARAM_LEN(dev) = 0; 399 } 400 401 /* clear all faults */ 402 /* coverity[callee_ptr_arith: FALSE] */ 403 rv = pmbus_write(unit, devno, PMBUS_CMD_CLEAR_FAULTS, &data8, 0); 404 if (SOC_FAILURE(rv)) { 405 line = __LINE__; 406 goto err_return; 407 } 408 409 /* enable operation commands over the PMBus */ 410 datalen = 1; 411 rv =pmbus_read(unit, devno, PMBUS_CMD_ON_OFF_CONFIG, &data8, &datalen); 412 if (SOC_FAILURE(rv)) { 413 line = __LINE__; 414 goto err_return; 415 } 416 417 data8 |= 0xf; 418 rv = pmbus_write(unit, devno, PMBUS_CMD_ON_OFF_CONFIG, &data8, 1); 419 if (SOC_FAILURE(rv)) { 420 line = __LINE__; 421 goto err_return; 422 } 423 424 /* get MFR ID and MFR MODEL */ 425 rv = pmbus_read(unit, devno, PMBUS_CMD_MFR_ID, &mfr_id, &datalen); 426 if (SOC_FAILURE(rv)) { 427 line = __LINE__; 428 goto err_return; 429 } 430 431 datalen = 2; 432 rv = pmbus_read(unit, devno, PMBUS_CMD_MFR_MODEL, (uint8*)&mfr_model, &datalen); 433 if (SOC_FAILURE(rv)) { 434 line = __LINE__; 435 goto err_return; 436 } 437 438 /* MFR special init */ 439 if((mfr_id == 0x1) && (mfr_model == 0x2)) { 440 /* NCP4200 device */ 441 data8 = NCP4200_MID_DACVAL; 442 rv = pmbus_write(unit, devno, PMBUS_CMD_VOUT_COMMAND, &data8, 1); 443 if (SOC_FAILURE(rv)) { 444 line = __LINE__; 445 goto err_return; 446 } 447 if (soc_property_get(unit, "voltage_control", 1)) { 448 datalen = 1; 449 rv = pmbus_read(unit, devno, I2C_ADP4000_CMD_CONFIG_1A, &data8, &datalen); 450 if (SOC_FAILURE(rv)) { 451 line = __LINE__; 452 goto err_return; 453 } 454 data8 |= 1 << 3; 455 rv = pmbus_write(unit, devno, I2C_ADP4000_CMD_CONFIG_1A, &data8, 1); 456 if (SOC_FAILURE(rv)) { 457 line = __LINE__; 458 goto err_return; 459 } 460 datalen = 1; 461 rv = pmbus_read(unit, devno, I2C_ADP4000_CMD_CONFIG_1B, &data8, &datalen); 462 if (SOC_FAILURE(rv)) { 463 line = __LINE__; 464 goto err_return; 465 } 466 data8 |= 1 << 3; 467 rv = pmbus_write(unit, devno, I2C_ADP4000_CMD_CONFIG_1B, &data8, 1); 468 if (SOC_FAILURE(rv)) { 469 line = __LINE__; 470 goto err_return; 471 } 472 } else { 473 datalen = 1; 474 rv = pmbus_read(unit, devno, I2C_ADP4000_CMD_CONFIG_1A, &data8, &datalen); 475 if (SOC_FAILURE(rv)) { 476 line = __LINE__; 477 goto err_return; 478 } 479 data8 &= ~(1 << 3); 480 rv = pmbus_write(unit, devno, I2C_ADP4000_CMD_CONFIG_1A, &data8, 1); 481 if (SOC_FAILURE(rv)) { 482 line = __LINE__; 483 goto err_return; 484 } 485 datalen = 1; 486 rv = pmbus_read(unit, devno, I2C_ADP4000_CMD_CONFIG_1B, &data8, &datalen); 487 if (SOC_FAILURE(rv)) { 488 line = __LINE__; 489 goto err_return; 490 } 491 data8 &= ~(1 << 3); 492 rv = pmbus_write(unit, devno, I2C_ADP4000_CMD_CONFIG_1B, &data8, 1); 493 if (SOC_FAILURE(rv)) { 494 line = __LINE__; 495 goto err_return; 496 } 497 } 498 rv = pmbus_ioctl(unit, devno, PMBUS_IOC_SET_DAC, &ncp4200_dac_params, 1); 499 if (SOC_FAILURE(rv)) { 500 line = __LINE__; 501 goto err_return; 502 } 503 } else if ((mfr_id == 0x1A) && (mfr_model == 0x1233)) { 504 /* NCP81233 device */ 505 rv = pmbus_ioctl(unit, devno, PMBUS_IOC_SET_DAC, &ncp81233_dac_params, 1); 506 if (SOC_FAILURE(rv)) { 507 line = __LINE__; 508 goto err_return; 509 } 510 } 511 512 soc_i2c_devdesc_set(unit, devno, "Pmbus Voltage Control"); 513 514 LOG_VERBOSE(BSL_LS_SOC_COMMON, 515 (BSL_META_U(unit, 516 "pmbus_init: %s, devNo=0x%x\n"), 517 soc_i2c_devname(unit, devno), devno)); 518 return rv; 519 520 err_return: 521 LOG_ERROR(BSL_LS_SOC_COMMON, 522 (BSL_META_U(unit, "pmbus init error: %s, line = %d\n"), 523 soc_i2c_devname(unit, devno), line)); 524 sal_free(dev->priv_data); 525 dev->priv_data = NULL; 526 return rv; 527 } 528 529 STATIC int 530 pmbus_deinit(int unit, int devno) 531 { 532 int rv = SOC_E_NONE; 533 i2c_device_t *dev = soc_i2c_device(unit, devno); 534 535 if (dev != NULL) { 536 if (dev->priv_data != NULL) { 537 sal_free(dev->priv_data); 538 dev->priv_data = NULL; 539 } 540 } else { 541 rv = SOC_E_INTERNAL; 542 } 543 544 return rv; 545 } 546 547 /* pmbus voltage control Chip Driver callout */ 548 i2c_driver_t _soc_i2c_pmbus_driver = { 549 0x0, 0x0, /* System assigned bytes */ 550 PMBUS_DEVICE_TYPE, 551 pmbus_read, 552 pmbus_write, 553 pmbus_ioctl, 554 pmbus_init, 555 pmbus_deinit, 556 };