max6653.c (12091B)
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 * [BSC] - Broadcom Serical Control (I2C constroller) 8 * | 9 * ==========O=======o================ I2C bus 10 * | 11 * [pca9548 - 8-port mux] 12 * | | | | | | | | 13 * [eeprom] - | | | | | | | 14 * [max6653] - | | | | | | 15 * [max6653] - | | | 16 * [max6653] - | | 17 * [max6653] - - [dpm73] 18 */ 19 20 21 #if defined(INCLUDE_I2C) && defined(BCM_FE2000_SUPPORT) 22 #include <shared/bsl.h> 23 24 #include <sal/types.h> 25 #include <soc/debug.h> 26 #include <soc/drv.h> 27 #include <soc/error.h> 28 #include <soc/bsc.h> 29 #include <shared/bsl.h> 30 extern unsigned int 31 sbFe2000UtilIICRead( int unit, 32 unsigned int slave_dev_addr, 33 unsigned int reg_index, 34 unsigned int *data); 35 36 extern unsigned int 37 sbFe2000UtilIICWrite( int unit, 38 unsigned int slave_dev_addr, 39 unsigned int reg_index, 40 unsigned int data); 41 42 static void sensor_show(int unit, int devno); 43 static int max6653_read(int unit, int devno, uint32 reg, uint32 *data); 44 static int max6653_write(int unit, int devno, uint32 reg, uint32 data); 45 46 int soc_bsc_max6653_set(int unit, int devno, int speed) 47 { 48 int retv; 49 uint32 reg_val = 0; 50 51 if (!soc_bsc_is_attached(unit)) { 52 soc_bsc_attach(unit); 53 } 54 55 if (soc_bsc_devtype(unit, devno) != MAX6653_DEVICE_TYPE) { 56 LOG_CLI((BSL_META_U(unit, 57 "Incorrect device type: %d should be %d\n"), 58 soc_bsc_devtype(unit, devno), MAX6653_DEVICE_TYPE)); 59 return SOC_E_PARAM; 60 } 61 62 /* 63 * Reset MAX6653 registers to default values 64 * 0x01 - configuration register 2 65 */ 66 retv = max6653_write(unit, devno, 0x01, 0x80); 67 if (retv < 0) { 68 return retv; 69 } 70 sal_usleep(1000); 71 retv = max6653_read(unit, devno, 0x01, ®_val); 72 if (retv < 0) { 73 return retv; 74 } 75 76 /* 77 * enable fan control and monitor 78 * 0x01 - Enable fan-speed control 79 * 0x04 - Tachometer digital/analog input selection: analog input 80 * 0x08 - Invert the PWM output: PWM active high 81 * 0x10 - FAN_FAULT output enable: enabled 82 */ 83 retv = max6653_write(unit, devno, 0x00, 0x1d); 84 if (retv < 0) { 85 return retv; 86 } 87 88 /* 89 * set fan speed 90 * 0x22 - fan-speed configuration register 91 */ 92 retv = max6653_write(unit, devno, 0x22, speed); 93 if (retv < 0) { 94 return retv; 95 } 96 97 return 0; 98 } 99 static unsigned int regmap[0x40] = { 100 0xFF, 0x01, 0x02, 0x03, 0x00, 0x00, 0x06, 0x00, 101 0x08, 0x00, 0x0A, 0x0B, 0x00, 0x0D, 0x0E, 0x00, 102 0x10, 0x00, 0x00, 0x00, 0x00, 0x15, 0x16, 0x00, 103 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x00, 0x00, 0x00, 104 0x20, 0x00, 0x22, 0x23, 0x24, 0x25, 0x00, 0x00, 105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 107 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x3E, 0x3F, 108 }; 109 110 void soc_bsc_max6653_show(int unit) 111 { 112 int devno, ndev; 113 114 if (!soc_bsc_is_attached(unit)) { 115 soc_bsc_attach(unit); 116 sal_usleep(500000); 117 } 118 119 ndev = soc_bsc_device_count(unit); 120 for (devno = 0; devno < ndev; devno++) { 121 if (soc_bsc_devtype(unit, devno) == MAX6653_DEVICE_TYPE) { 122 sensor_show(unit, devno); 123 if (bsl_check(bslLayerSoc, bslSourceI2c, bslSeverityNormal, unit)) { 124 int iii, retv; 125 uint32 regv = 0; 126 LOG_CLI((BSL_META_U(unit, 127 "\nChannel MAP 0x%02x\n"), 128 BSCBUS(unit)->devs[devno]->chan)); 129 for(iii = 0x0; iii <= 0x3F; iii++) { 130 if ((iii % 8) == 0) { 131 LOG_CLI((BSL_META_U(unit, 132 "\nTS_FC 0x%02x : "), iii)); 133 } 134 if (regmap[iii]) { 135 retv = max6653_read(unit, devno, iii, ®v); 136 if (retv != 0) { 137 return; 138 } 139 LOG_CLI((BSL_META_U(unit, 140 "0x%02x "), regv)); 141 } else { 142 LOG_CLI((BSL_META_U(unit, 143 "---- "))); 144 } 145 } 146 LOG_CLI((BSL_META_U(unit, 147 "\n"))); 148 } 149 } 150 } 151 } 152 153 static void max6653_thread(void *unitp) 154 { 155 soc_bsc_bus_t *bscbus; 156 int unit; 157 158 unit = PTR_TO_INT(unitp); 159 bscbus = BSCBUS(unit); 160 161 while (bscbus->mon_delay) { 162 LOG_CLI((BSL_META_U(unit, 163 "\n -- unit %d: sensor monitoring every %d seconds --\n"), 164 unit, bscbus->mon_delay)); 165 soc_bsc_max6653_show(unit); 166 sal_usleep(bscbus->mon_delay * SECOND_USEC); 167 } 168 LOG_CLI((BSL_META_U(unit, 169 "unit %d: sensor monitoring completed\n"), unit)); 170 sal_thread_exit(0); 171 } 172 173 void soc_bsc_max6653_watch(int unit, int enable, int nsecs) 174 { 175 soc_bsc_bus_t *bscbus; 176 177 if (!soc_bsc_is_attached(unit)) { 178 soc_bsc_attach(unit); 179 } 180 bscbus = BSCBUS(unit); 181 182 if (!enable) { 183 bscbus->mon_delay = 0; 184 return; 185 } 186 bscbus->mon_delay = nsecs; 187 188 sal_thread_create("", SAL_THREAD_STKSZ, 189 50, 190 (void (*)(void*))max6653_thread, 191 INT_TO_PTR(unit)); 192 LOG_CLI((BSL_META_U(unit, 193 "unit %d: sensor monitoring enabled\n"), unit)); 194 } 195 196 static void sensor_show(int unit, int devno) 197 { 198 int retv; 199 uint32 local = 0; 200 uint32 remote = 0; 201 uint32 local_offset = 0; 202 uint32 remote_offset = 0; 203 uint32 fan_speed_count = 0; 204 uint32 reg_config0 = 0; 205 206 /* 207 * Read local temperature 208 */ 209 retv = max6653_read(unit, devno, 0x0A, &local); 210 if (retv != 0) { 211 return; 212 } 213 214 /* 215 * Read remote temperature 216 */ 217 retv = max6653_read(unit, devno, 0x0B, &remote); 218 if (retv != 0) { 219 return; 220 } 221 222 /* 223 * Read local offset 224 */ 225 retv = max6653_read(unit, devno, 0x0D, &local_offset); 226 if (retv != 0) { 227 return; 228 } 229 230 /* 231 * Read remote offset 232 */ 233 retv = max6653_read(unit, devno, 0x0E, &remote_offset); 234 if (retv != 0) { 235 return; 236 } 237 238 LOG_CLI((BSL_META_U(unit, 239 "sensor %d: local: %dC remote: %dC"), devno, 240 local + local_offset, remote + remote_offset)); 241 242 /* 243 * Fan speed count 244 */ 245 retv = max6653_read(unit, devno, 0x00, ®_config0); 246 if (retv < 0) { 247 LOG_CLI((BSL_META_U(unit, 248 " fan speed reading error\n"))); 249 return; 250 } 251 252 if (reg_config0 & 0x01) { 253 retv = max6653_read(unit, devno, 0x08, &fan_speed_count); 254 if (retv < 0) { 255 LOG_CLI((BSL_META_U(unit, 256 " fan speed reading error\n"))); 257 return; 258 } 259 if (fan_speed_count != 0) { 260 LOG_CLI((BSL_META_U(unit, 261 " fan speed (RPM): %d\n"), 262 675000/(fan_speed_count * 2) - 1323)); 263 } 264 } else { 265 LOG_CLI((BSL_META_U(unit, 266 " fan control inactive\n"))); 267 } 268 } 269 270 static int max6653_read(int unit, int devno, uint32 reg, uint32 *data) 271 { 272 soc_bsc_bus_t *bscbus = BSCBUS(unit); 273 int chan = bscbus->devs[devno]->chan; 274 int saddr = bscbus->devs[devno]->saddr; 275 int mux = bscbus->devs[devno]->mux; 276 int retv; 277 278 BSC_LOCK(unit); 279 280 /* Select MUX to slave device */ 281 retv = sbFe2000UtilIICWrite(unit, mux, chan, chan); 282 if (retv != 0) { 283 BSC_UNLOCK(unit); 284 return retv; 285 } 286 retv = sbFe2000UtilIICRead(unit, saddr, reg, data); 287 if (retv != 0) { 288 BSC_UNLOCK(unit); 289 return retv; 290 } 291 292 BSC_UNLOCK(unit); 293 return SOC_E_NONE; 294 } 295 296 static int max6653_write(int unit, int devno, uint32 reg, uint32 data) 297 { 298 soc_bsc_bus_t *bscbus = BSCBUS(unit); 299 int chan = bscbus->devs[devno]->chan; 300 int saddr = bscbus->devs[devno]->saddr; 301 int mux = bscbus->devs[devno]->mux; 302 int retv; 303 304 BSC_LOCK(unit); 305 306 /* Select MUX to slave device */ 307 retv = sbFe2000UtilIICWrite(unit, mux, chan, chan); 308 if (retv != 0) { 309 BSC_UNLOCK(unit); 310 return retv; 311 } 312 313 retv = sbFe2000UtilIICWrite(unit, saddr, reg, data); 314 if (retv != 0) { 315 BSC_UNLOCK(unit); 316 return retv; 317 } 318 319 BSC_UNLOCK(unit); 320 return SOC_E_NONE; 321 } 322 323 324 325 static int max6653_ioctl(int unit, int devno, int opcode, void* data, int len) 326 { 327 int retv; 328 uint32 device_id, manufacturer_id; 329 330 switch(opcode) { 331 case BSC_IOCTL_DEVICE_PRESENT: 332 333 retv = max6653_read(unit, devno, BSC_MAX6653_DEVID_OFF, &device_id); 334 if (retv != 0) { 335 return 0; 336 } 337 338 retv = max6653_read(unit, devno, BSC_MAX6653_MANUF_OFF, &manufacturer_id); 339 if (retv != 0) { 340 return 0; 341 } 342 343 if ((device_id == BSC_MAX6653_DEVID) && (manufacturer_id == BSC_MAX6653_MANUF)) { 344 return 1; /* found */ 345 } else { 346 return 0; /* not found */ 347 } 348 break; 349 350 default: 351 break; 352 } 353 return 0; 354 } 355 356 static int max6653_init(int unit, int devno) 357 { 358 int retv; 359 uint32 reg_val = 0; 360 361 /* 362 * Reset MAX6653 registers to default values 363 */ 364 retv = max6653_write(unit, devno, 0x01, 0x80); 365 if (retv < 0) { 366 return retv; 367 } 368 sal_usleep(1000); 369 retv = max6653_read(unit, devno, 0x01, ®_val); 370 if (retv < 0) { 371 return retv; 372 } 373 /* 374 * enable fan control and monitor 375 * 0x01 - Enable fan-speed control 376 * 0x04 - Tachometer digital/analog input selection: analog input 377 * 0x08 - Invert the PWM output: PWM active high 378 * 0x10 - FAN_FAULT output enable: enabled 379 */ 380 retv = max6653_write(unit, devno, 0x00, 0x1d); 381 if (retv < 0) { 382 return retv; 383 } 384 385 /* 386 * set fan characteristics register 387 */ 388 retv = max6653_write(unit, devno, 0x20, 0x7d); 389 if (retv < 0) { 390 return retv; 391 } 392 393 /* 394 * set fan speed 395 */ 396 retv = max6653_write(unit, devno, 0x22, 15); 397 if (retv < 0) { 398 return retv; 399 } 400 401 return SOC_E_NONE; 402 } 403 404 bsc_driver_t _soc_bsc_max6653_driver = { 405 0x0, /* flags */ 406 0x0, /* devno */ 407 MAX6653_DEVICE_TYPE, /* id */ 408 max6653_read, 409 max6653_write, 410 max6653_ioctl, 411 max6653_init, 412 }; 413 414 /* 415 * Useful debug routine 416 */ 417 void soc_bsc_setmux(int unit, int chan) 418 { 419 int retv; 420 421 /* Make sure that we're already attached, or go get attached */ 422 if (!soc_bsc_is_attached(unit)) { 423 soc_bsc_attach(unit); 424 } 425 426 BSC_LOCK(unit); 427 428 /* Select MUX to slave device */ 429 retv = sbFe2000UtilIICWrite(unit, BSC_PCA9548_SADDR, 0, 1 << chan); 430 if (retv != 0) { 431 BSC_UNLOCK(unit); 432 return; 433 } 434 BSC_UNLOCK(unit); 435 } 436 437 438 /* 439 * Useful debug routine 440 * Mux channel is pre-set 441 */ 442 void soc_bsc_readmax(int unit) 443 { 444 int retv; 445 uint32 device_id = 0, manufacturer_id = 0; 446 447 /* Make sure that we're already attached, or go get attached */ 448 if (!soc_bsc_is_attached(unit)) { 449 soc_bsc_attach(unit); 450 } 451 452 BSC_LOCK(unit); 453 454 retv = sbFe2000UtilIICRead(unit, 455 BSC_MAX6653_SADDR, BSC_MAX6653_DEVID_OFF, &device_id); 456 if (retv != 0) { 457 BSC_UNLOCK(unit); 458 return; 459 } 460 461 retv = sbFe2000UtilIICRead(unit, 462 BSC_MAX6653_SADDR, BSC_MAX6653_MANUF_OFF, &manufacturer_id); 463 if (retv != 0) { 464 BSC_UNLOCK(unit); 465 return; 466 } 467 BSC_UNLOCK(unit); 468 469 LOG_CLI((BSL_META_U(unit, 470 "devid: 0x%02x vend: 0x%02x\n"), device_id, manufacturer_id)); 471 } 472 473 #else/* BCM_FE2000_SUPPORT && INCLUDE_I2C */ 474 int _soc_i2c_max6653_not_empty; 475 #endif /* BCM_FE2000_SUPPORT && INCLUDE_I2C */