openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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, &reg_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, &regv);
    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, &reg_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, &reg_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 */