ltm4678.c (17207B)
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 LTM4678 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 /* Divided by 2^12 for voltage conversion */ 18 #define L16_TO_V(val) ((val)*100000/4096/100000) 19 #define V_TO_L16(val) ((val)*4096) 20 #define L16_TO_UV(val) ((val)*100000/4096*10) 21 #define UV_TO_L16(val) ((val)/10*4096/100000) 22 23 #define L16_RANGE_UPPER(L16, range) ((L16) + (int)(range)*L16/100000) 24 #define L16_RANGE_LOWER(L16, range) ((L16) - (int)(range)*L16/100000) 25 26 #define MAX_VS_CONFIG 2 27 28 #define POWER(exponent, input_val) exponent < 0 ? \ 29 (int)((int) (input_val) << (exponent*(-1))): \ 30 (int)((int) (input_val*1000000) >> \ 31 exponent)/1000000 32 33 typedef struct device_data_s { 34 sal_mutex_t lock; /* mutex lock for device operation */ 35 dac_calibrate_t *dac_params; /*dac params for each device channel*/ 36 int dac_param_len; 37 int flags; 38 i2c_saddr_t rail_saddr; 39 } device_data_t; 40 41 #define DEV_DAC_PARAMS(dev) \ 42 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->dac_params) 43 #define DEV_DAC_PARAM_LEN(dev) \ 44 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->dac_param_len) 45 #define DEV_FLAGS(dev) \ 46 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->flags) 47 #define DEV_RAIL_SADDR(dev) \ 48 (((device_data_t *)(((i2c_device_t *)(dev))->priv_data))->rail_saddr) 49 50 51 #define DEV_CHECK_RETURN(dev) \ 52 { \ 53 if ((dev) == NULL) { \ 54 return SOC_E_INTERNAL; \ 55 } \ 56 } 57 58 #define DEV_PRIVDATA_CHECK_RETURN(dev) \ 59 { \ 60 DEV_CHECK_RETURN(dev) \ 61 if ((dev)->priv_data == NULL) { \ 62 return SOC_E_INTERNAL; \ 63 } \ 64 } 65 66 67 static sal_mutex_t ioctl_lock = NULL; 68 69 /* 70 * Convert a floating point value into a 71 * LinearFloat5_11 formatted word 72 */ 73 int 74 #ifdef COMPILER_HAS_DOUBLE 75 ltm4678_float_to_L11(double input_val, uint16* data) 76 #else 77 ltm4678_float_to_L11(int input_val, uint16* data) 78 #endif 79 { 80 uint16 uExponent, uMantissa; 81 /* set exponent to -16 */ 82 int16 exponent = -16; 83 /* extract mantissa from input value */ 84 int mantissa = POWER(exponent, input_val); 85 86 /* Search for an exponent that produces 87 * a valid 11-bit mantissa */ 88 do 89 { 90 if((mantissa >= -1024) && 91 (mantissa <= +1023)) 92 { 93 break; /* stop if mantissa valid */ 94 } 95 exponent++; 96 mantissa = POWER(exponent, input_val); 97 } while (exponent < +15); 98 99 /* Format the exponent of the L11 */ 100 uExponent = exponent << 11; 101 /* Format the mantissa of the L11 */ 102 uMantissa = mantissa & 0x07FF; 103 /* Compute value as exponent | mantissa */ 104 *(data) = uExponent | uMantissa; 105 return SOC_E_NONE; 106 } 107 108 /* 109 * Convert a LinearFloat5_11 formatted word 110 * into a floating point value 111 */ 112 int 113 ltm4678_L11_to_float(uint16 input_val, void *data) 114 { 115 /* extract exponent as MS 5 bits */ 116 int8 exponent = input_val >> 11; 117 /* extract mantissa as LS 11 bits */ 118 int16 mantissa = input_val & 0x7ff; 119 /* sign extend exponent from 5 to 8 bits */ 120 if( exponent > 0x0F ) exponent |= 0xE0; 121 /* sign extend mantissa from 11 to 16 bits */ 122 if( mantissa > 0x03FF ) mantissa |= 0xF800; 123 #ifdef COMPILER_HAS_DOUBLE 124 /* compute value as mantissa * 2^(exponent) */ 125 *(double *)data= exponent < 0 ? 126 (double) ((mantissa*1000000) >> 127 (exponent*(-1)))/1000000: 128 (double) (mantissa << exponent); 129 #else 130 *(int *)data= exponent < 0 ? 131 (((mantissa)*1000000) >> (exponent*(-1))): 132 ((mantissa) << exponent)*100000; 133 #endif 134 return SOC_E_NONE; 135 } 136 137 STATIC int 138 ltm4678_wait_for_not_busy(int unit, int devno) 139 { 140 int rv = SOC_E_NONE; 141 uint8 mfr_status, saddr; 142 uint32 usec, wait_usec; 143 144 wait_usec = 0; 145 usec = 10; 146 147 saddr = soc_i2c_addr(unit, devno); 148 149 while(wait_usec < 1000000) { 150 SOC_IF_ERROR_RETURN 151 (soc_i2c_read_byte_data(unit, saddr,PMBUS_CMD_MFR_COMMON, 152 &mfr_status)); 153 soc_i2c_device(unit, devno)->rbyte++; 154 if ((mfr_status & 0x70) == 0x70) { 155 /* Bit 6 : Chip not busy */ 156 /* Bit 5 : calculations not pending */ 157 /* Bit 4 : OUTPUT not in transition */ 158 break; 159 } else { 160 sal_udelay(usec); 161 wait_usec += usec; 162 } 163 } 164 165 if ((mfr_status & 0x70) != 0x70) { 166 LOG_WARN(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "unit %d i2c %s :ltm4678 is busy !\n"), 167 unit, soc_i2c_devname(unit, devno))); 168 rv = SOC_E_TIMEOUT; 169 } 170 return rv; 171 } 172 173 174 STATIC int 175 ltm4678_read(int unit, int devno, uint16 addr, uint8* data, uint32* len) 176 { 177 int rv = SOC_E_NONE; 178 uint8 saddr; 179 180 saddr = soc_i2c_addr(unit, devno); 181 182 if (*len == 0) { 183 return SOC_E_NONE; 184 } 185 if (*len == 1) { 186 /* reads a single byte from a device, from a designated register*/ 187 rv = soc_i2c_read_byte_data(unit, saddr, addr,data); 188 soc_i2c_device(unit, devno)->rbyte++; 189 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 190 "unit %d i2c %s: LTM4678_read: " 191 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d, " 192 "rv = %d\n"), 193 unit, soc_i2c_devname(unit,devno), 194 saddr, addr, *data, *len, rv)); 195 } else if (*len == 2) { 196 /* reads a single word from a device, from a designated register*/ 197 rv = soc_i2c_read_word_data(unit, saddr, addr,(uint16 *)data); 198 soc_i2c_device(unit, devno)->rbyte +=2; 199 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 200 "unit %d i2c %s: LTM4678_read: " 201 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d, " 202 "rv = %d\n"), 203 unit, soc_i2c_devname(unit,devno), 204 saddr, addr, *(uint16 *)data, *len, rv)); 205 } else { 206 /* not supported for now */ 207 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 208 "unit %d i2c %s: LTM4678_read fail: " 209 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d\n"), 210 unit, soc_i2c_devname(unit,devno), 211 saddr, addr, *data, *len)); 212 } 213 return rv; 214 } 215 216 STATIC int 217 _ltm4678_write(int unit, int devno, uint8 saddr, uint16 addr, uint8* data, uint32 len) 218 { 219 int rv = SOC_E_NONE; 220 unsigned short val; 221 222 if (len == 0) { 223 /* simply writes command code to device */ 224 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "i2c %s: LTM4678 write: " 225 "saddr = 0x%x, addr = 0x%x, len = %d\n"), 226 soc_i2c_devname(unit, devno), saddr, addr, len)); 227 rv = soc_i2c_write_byte(unit, saddr, addr); 228 } else if (len == 1) { 229 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "i2c %s: LTM4678 write: " 230 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d\n"), 231 soc_i2c_devname(unit, devno), saddr, addr, *data, len)); 232 rv = soc_i2c_write_byte_data(unit, saddr, addr, *data); 233 soc_i2c_device(unit, devno)->tbyte++; 234 } else if (len == 2) { 235 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "i2c %s: LTM4678 write: " 236 "saddr = 0x%x, addr = 0x%x, data = 0x%x, len = %d\n"), 237 soc_i2c_devname(unit, devno), 238 saddr, addr, *(uint16 *)data, len)); 239 val = *(unsigned short *)data; 240 rv = soc_i2c_write_word_data(unit, saddr, addr, val); 241 soc_i2c_device(unit, devno)->tbyte += 2; 242 } 243 return rv; 244 } 245 246 STATIC int 247 ltm4678_write(int unit, int devno, uint16 addr, uint8* data, uint32 len) 248 { 249 uint8 saddr; 250 251 saddr = soc_i2c_addr(unit, devno); 252 253 return (_ltm4678_write(unit, devno, saddr, addr, data, len)); 254 255 } 256 257 STATIC int 258 ltm4678_rail_write(int unit, int devno, uint16 addr, uint8* data, uint32 len) 259 { 260 uint8 rail_saddr; 261 262 rail_saddr = DEV_RAIL_SADDR(soc_i2c_device(unit, devno)); 263 264 if (rail_saddr == 0) { 265 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 266 "Rail saddr not set for dev %s\n"), 267 soc_i2c_devname(unit, devno))); 268 return SOC_E_INTERNAL; 269 } 270 return (_ltm4678_write(unit, devno, rail_saddr, addr, data, len)); 271 272 } 273 274 STATIC int 275 ltm4678_check_page(int unit, int devno, int ch) 276 { 277 int rv; 278 uint8 page; 279 uint32 len; 280 281 len = sizeof(char); 282 rv = ltm4678_read(unit, devno, PMBUS_CMD_PAGE, &page, &len); 283 if (rv != SOC_E_NONE) { 284 return rv; 285 } 286 287 if (page != ch) { 288 page = ch; 289 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "LTM4678 %d set page to %d\n"), 290 soc_i2c_addr(unit, devno), page)); 291 rv = ltm4678_write(unit, devno, PMBUS_CMD_PAGE, &page, sizeof(char)); 292 } 293 return rv; 294 } 295 296 /* 297 * NOTE NOTE NOTE: 298 * All tables (dac_calibrate_t) passed to the ioctl() have size > 1 299 * and the index is always within this range. 300 */ 301 STATIC int 302 ltm4678_ioctl(int unit, int devno, int opcode, 303 void* data, int len) 304 { 305 int rv = SOC_E_NONE; 306 #ifdef COMPILER_HAS_DOUBLE 307 double fval; 308 #else 309 int fval; 310 #endif 311 uint16 dac; 312 uint32 datalen = 2; 313 unsigned short voltage; 314 /* Using mutex lock to ensure thread-safe for ioctl operations */ 315 sal_mutex_take(ioctl_lock, sal_mutex_FOREVER); 316 317 /* length field is actually used as an index into the dac_params table*/ 318 switch (opcode) { 319 case I2C_LTC_IOC_READ_VOUT: 320 if ((rv=ltm4678_check_page(unit, devno, len)) < 0) { 321 cli_out("Error: failed to set page %d in LTM4678 device.\n", len); 322 break; 323 } 324 if ((rv=ltm4678_wait_for_not_busy(unit, devno)) < 0) { 325 cli_out("Error: Device LTM4678 is busy.\n"); 326 break; 327 } 328 datalen=2; 329 if ((rv=ltm4678_read(unit,devno, PMBUS_CMD_READ_VOUT, (void *)&dac, &datalen)) < 0) { 330 cli_out("Error: Failed to read VOUT of LTM4678 Device.\n"); 331 break; 332 } 333 fval=dac; 334 #ifdef COMPILER_HAS_DOUBLE 335 fval=L16_TO_V(fval ); 336 *(double *)data=fval; 337 #else 338 fval=L16_TO_UV(fval); 339 *(int *)data=(fval); 340 #endif 341 break; 342 343 case I2C_LTC_IOC_READ_IOUT: 344 if ((rv=ltm4678_check_page(unit, devno, len)) < 0) { 345 cli_out("Error: failed to set page %d in LTM4678 device.\n", len); 346 break; 347 } 348 if ((rv=ltm4678_wait_for_not_busy(unit, devno)) < 0) { 349 cli_out("Error: LTM4678 Device is busy.\n"); 350 break; 351 } 352 if ((rv=ltm4678_read(unit, devno,PMBUS_CMD_READ_IOUT, (void *)&dac, &datalen)) < 0) { 353 cli_out("Error:Failed to read current in LTM4678 Device.\n"); 354 break; 355 } 356 rv=ltm4678_L11_to_float(dac, &fval); 357 #ifdef COMPILER_HAS_DOUBLE 358 *(double *)data=fval*1000; 359 #else 360 *(int *)data=fval; 361 #endif 362 break; 363 364 case I2C_LTC_IOC_READ_POUT: 365 datalen=2; 366 if ((rv=ltm4678_check_page(unit, devno, len)) < 0) { 367 cli_out("Error: failed to set page %d in LTM4678 device.\n", len); 368 break; 369 } 370 if ((rv=ltm4678_wait_for_not_busy(unit, devno)) < 0) { 371 cli_out("Error: LTM4678 Device is busy.\n"); 372 sal_mutex_give(ioctl_lock); 373 return rv; 374 } 375 376 if ((rv=ltm4678_read(unit,devno, PMBUS_CMD_READ_POUT, (void *)&dac, &datalen)) < 0) { 377 cli_out("Error: failed to read power in LTM4678 device.\n"); 378 break; 379 } 380 rv=ltm4678_L11_to_float(dac, &fval); 381 #ifdef COMPILER_HAS_DOUBLE 382 *(double *)data=fval*1000; 383 #else 384 *(int *)data=fval; 385 #endif 386 break; 387 388 case I2C_LTC_IOC_SET_VOUT: 389 /* Conversion of output voltage */ 390 #ifdef COMPILER_HAS_DOUBLE 391 fval = *((double*)data); 392 voltage = (fval*4096); 393 #else 394 fval = *((int*)data); 395 /*2^12 conversion and changing from uVolt */ 396 voltage = (fval*4096)/1000000; 397 #endif 398 dac = voltage; 399 /* Show what we are doing, for now ... */ 400 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META_U(unit, 401 "unit %d i2c %s: LTM4678 ioctl " 402 "I2C_DAC_IOC_SET_VOUT : voltage = %d, len = %d\n"), 403 unit, soc_i2c_devname(unit,devno), voltage, len)); 404 405 rv = ltm4678_rail_write(unit, devno, PMBUS_CMD_VOUT_COMMAND,(void *) &dac, 2); 406 break; 407 408 default: 409 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 410 "unit %d i2c %s: ltm4678_ioctl: invalid opcode (%d)\n"), 411 unit, soc_i2c_devname(unit,devno), opcode)); 412 break; 413 } 414 sal_mutex_give(ioctl_lock); 415 return rv; 416 } 417 418 STATIC int 419 ltm4678_init(int unit, int devno, void* data, int len) 420 { 421 int rv = SOC_E_NONE; 422 i2c_device_t *dev = soc_i2c_device(unit, devno); 423 char *devname; 424 uint8 data8; 425 426 if (dev == NULL) { 427 return SOC_E_INTERNAL; 428 } 429 devname = (char *)soc_i2c_devname(unit, devno); 430 if (dev->priv_data == NULL) { 431 dev->priv_data = sal_alloc(sizeof(device_data_t), devname); 432 if (dev->priv_data == NULL) { 433 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 434 "Fail to allocate private data fo dev %s\n"), 435 soc_i2c_devname(unit, devno))); 436 return SOC_E_MEMORY; 437 } 438 sal_memset(dev->priv_data, 0, sizeof(device_data_t)); 439 } 440 441 if (ioctl_lock == NULL) { 442 ioctl_lock = sal_mutex_create("ltm4678_ioctl_lock"); 443 if (ioctl_lock == NULL) { 444 LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 445 "Fail to create ltm4678_ioctl_lock\n"))); 446 rv = SOC_E_MEMORY; 447 } 448 } 449 450 /* Using mutex lock to ensure thread-safe for ioctl operations */ 451 sal_mutex_take(ioctl_lock, sal_mutex_FOREVER); 452 /* bit3 1: control the LTM4678 output through VOUT command 453 * 0: control the output via VID input pins which is controlled by 454 * a PCF8574 device 455 */ 456 if ((rv=ltm4678_write(unit, devno, 457 PMBUS_CMD_CLEAR_FAULTS,(void *) &len, 0)) < 0) { 458 cli_out("Error: Failed to clear the faults of LTM4678 device.\n"); 459 sal_mutex_give(ioctl_lock); 460 return rv; 461 } 462 if ((rv=ltm4678_wait_for_not_busy(unit, devno)) < 0) { 463 cli_out("Error: LTM4678 Device is busy.\n"); 464 sal_mutex_give(ioctl_lock); 465 return rv; 466 } 467 468 len = 1; 469 if ((rv=ltm4678_read(unit, devno, 0xFA, (uint8 *)&DEV_RAIL_SADDR(dev), (void *)&len)) < 0) { 470 cli_out("Error: Failed to read 0xFA of LTM4678 device.\n"); 471 sal_mutex_give(ioctl_lock); 472 return rv; 473 } 474 475 /* bsl_printf("SADDR = 0x%02x DEV_RAIL_SADDR = 0x%02x\n", soc_i2c_addr(unit, devno), DEV_RAIL_SADDR(dev)); */ 476 soc_i2c_devdesc_set(unit, devno, "LTM4678 Voltage Control"); 477 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "ltm4678_init: %s, devNo=0x%x\n"), 478 soc_i2c_devname(unit,devno), devno)); 479 480 /* Setting Fault response to zero to prevent shut-down of device */ 481 data8 =0x00; 482 if ((rv=ltm4678_write(unit, devno, 483 PMBUS_CMD_VOUT_OV_FAULT_RES, &data8, 1)) < 0) { 484 cli_out("Error: failed to set OV fault response of LTM4678.\n"); 485 sal_mutex_give(ioctl_lock); 486 return rv; 487 } 488 if ((rv=ltm4678_wait_for_not_busy(unit, devno)) < 0) { 489 cli_out("Error: LTM4678 device is busy.\n"); 490 sal_mutex_give(ioctl_lock); 491 return rv; 492 } 493 494 data8 =0x0A; 495 if ((rv=ltm4678_write(unit, devno, PMBUS_CMD_ON_OFF_CONFIG, &data8, 1)) < 0) { 496 cli_out("Error: failed to set CONFIG register of LTM4678 device.\n"); 497 sal_mutex_give(ioctl_lock); 498 return rv; 499 } 500 /* Switching on LTC4678 device */ 501 data8 =0x80; 502 if ((rv=ltm4678_write(unit, devno, PMBUS_CMD_OPERATION, &data8, 1)) < 0) { 503 cli_out("Error: failed to set operation register of LTM4678 device.\n"); 504 sal_mutex_give(ioctl_lock); 505 return rv; 506 } 507 if ((rv=ltm4678_wait_for_not_busy(unit, devno)) < 0) { 508 cli_out("Error: LTM4678 Device is busy.\n"); 509 sal_mutex_give(ioctl_lock); 510 return rv; 511 } 512 513 sal_mutex_give(ioctl_lock); 514 return rv; 515 } 516 517 /* ltm4678 voltage control Chip Driver callout */ 518 i2c_driver_t _soc_i2c_ltm4678_driver = { 519 0x0, 0x0, /* System assigned bytes */ 520 LTM4678_DEVICE_TYPE, 521 ltm4678_read, 522 ltm4678_write, 523 ltm4678_ioctl, 524 ltm4678_init, 525 NULL, 526 };