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

ltc1427.c (7835B)


      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  * BCM56xx I2C Device Driver for Linear Technology 1427-50 DAC.
      8  * The LTC1427 DAC is used to control voltage outputs on various
      9  * SDK baseboards. See the LTC-1427-50 datasheet for more info.
     10  */
     11 #include <sal/types.h>
     12 #include <soc/debug.h>
     13 #include <soc/drv.h>
     14 #include <soc/error.h>
     15 #include <soc/i2c.h>
     16 #include <sal/core/libc.h>
     17 #include <shared/bsl.h>
     18  #include <soc/util.h>
     19 
     20 #ifdef	COMPILER_HAS_DOUBLE
     21 #define I2C_DATA_T      double
     22 #define I2C_DATA_F      "f"
     23 #else
     24 #define I2C_DATA_T      int
     25 #define I2C_DATA_F      "d"
     26 #endif
     27 
     28 /* Calibration table in effect */
     29 static dac_calibrate_t* dac_params;
     30 static int dac_param_len;
     31 
     32 STATIC int
     33 ltc1427_read(int unit, int devno,
     34 	  uint16 addr, uint8* data, uint32* len)
     35 {
     36     COMPILER_REFERENCE(unit);
     37     COMPILER_REFERENCE(devno);
     38     COMPILER_REFERENCE(addr);
     39     COMPILER_REFERENCE(data);
     40     COMPILER_REFERENCE(len);
     41 
     42     return SOC_E_NONE;
     43 }
     44 
     45 STATIC int
     46 ltc1427_write(int unit, int devno,
     47 	   uint16 addr, uint8* data, uint32 len)
     48 {
     49     int rv = SOC_E_NONE;
     50     uint16 dw = 0;
     51 
     52     if(!data || (len <=0))
     53 	return SOC_E_PARAM;
     54 
     55     /* Convert two bytes into single 16bit value */
     56     dw = data[0];
     57     dw <<= 8;
     58     dw |= data[1];
     59 
     60     dw = soc_ntohs(dw);
     61     dw &= ~0x8000; /* Make sure we never shut down DAC */
     62     rv = soc_i2c_write_word(unit, soc_i2c_addr(unit, devno), dw);
     63 
     64     soc_i2c_device(unit, devno)->tbyte +=2;
     65     return rv;
     66 }
     67 
     68 /*
     69  * NOTE NOTE NOTE:
     70  * All tables (dac_calibrate_t) passed to the ioctl() have size > 1
     71  * and the index is always within this range.
     72  */
     73 
     74 #define LTC1427_SET_SELECT_MIN  0
     75 #define LTC1427_SET_SELECT_MAX  1
     76 #define LTC1427_SET_SELECT_MID  2
     77 
     78 STATIC int
     79 ltc1427_setmin_max(int unit, int devno, int set_sel, int idx)
     80 {
     81     short data;
     82     int rv;
     83 
     84     /* set the default voltage */
     85     switch (set_sel) {
     86     case LTC1427_SET_SELECT_MAX:
     87         data = dac_params[idx].dac_max_hwval;
     88         break;
     89     case LTC1427_SET_SELECT_MID:
     90         data = dac_params[idx].dac_mid_hwval;
     91         break;
     92     case LTC1427_SET_SELECT_MIN:
     93         data = dac_params[idx].dac_min_hwval;
     94         break;
     95     default:
     96         return SOC_E_INTERNAL;
     97     }
     98     rv = ltc1427_write(unit, devno, 0, (uint8*)&data, sizeof(short));
     99 
    100     if (SOC_SUCCESS(rv)) {
    101 	/* Keep last value since DAC is write-only device */
    102         dac_params[idx].dac_last_val = data;
    103     }
    104     return rv;
    105 }
    106 
    107 #define LTC1427_SETMAX(unit,devno, idx) \
    108    ltc1427_setmin_max(unit, devno, LTC1427_SET_SELECT_MAX, idx)
    109 #define LTC1427_SETMIN(unit,devno, idx) \
    110    ltc1427_setmin_max(unit, devno, LTC1427_SET_SELECT_MIN, idx)
    111 #define LTC1427_SETMID(unit,devno, idx) \
    112    ltc1427_setmin_max(unit, devno, LTC1427_SET_SELECT_MID, idx)
    113 
    114 STATIC int
    115 ltc1427_ioctl(int unit, int devno,
    116 	   int opcode, void* data, int len)
    117 {
    118     int rv = SOC_E_NONE;
    119     I2C_DATA_T fval,tmp;
    120     uint16 dac;
    121     dac_calibrate_t* params = NULL;
    122 
    123     /* length field is actually used as an index into the dac_params table*/
    124     if( !data || ( (dac_params != NULL) && (len > dac_param_len)))
    125 	return SOC_E_PARAM;
    126 
    127     switch ( opcode ){
    128 
    129 	/* Upload calibration table */
    130     case I2C_DAC_IOC_SET_CALTAB:
    131 	params = (dac_calibrate_t*)data;
    132 	dac_params = params;
    133 	dac_param_len = len;
    134 	break;
    135 
    136     case I2C_DAC_IOC_SETDAC_MIN:
    137 	/* Set MIN voltage */
    138 	rv = LTC1427_SETMIN(unit, devno, len);
    139 	break;
    140 
    141     case I2C_DAC_IOC_SETDAC_MAX:
    142 	/* Set MAX voltage */
    143 	rv = LTC1427_SETMAX(unit, devno, len);
    144 	break;
    145 
    146     case I2C_DAC_IOC_SETDAC_MID:
    147 	/* Set mid-range voltage */
    148 	rv = LTC1427_SETMID(unit, devno, len);
    149 	break;
    150 
    151     case I2C_DAC_IOC_CALIBRATE_MAX:
    152 	/* Set MAX output value (from ADC) */
    153 	fval = *((I2C_DATA_T*)data);
    154         if (dac_params)
    155             dac_params[len].max = fval;
    156 	break;
    157 
    158     case I2C_DAC_IOC_CALIBRATE_MIN:
    159 	/* Set MIN output value (from ADC) */
    160 	fval = *((I2C_DATA_T*)data);
    161         if (dac_params)
    162 	    dac_params[len].min = fval;
    163 	break;
    164 
    165     case I2C_DAC_IOC_CALIBRATE_STEP:
    166 	/* Calibrate stepsize */
    167 
    168         if (dac_params) {
    169             dac_params[len].step =
    170                 (dac_params[len].use_max ? -1 : 1) *
    171                 (dac_params[len].max - dac_params[len].min) / 
    172                 (dac_params[len].dac_max_hwval - dac_params[len].dac_min_hwval);
    173             LOG_VERBOSE(BSL_LS_SOC_COMMON,
    174                         (BSL_META_U(unit,
    175                                     "unit %d i2c %s: LTC1427 calibration on function %s:"
    176                                     "(max=%"I2C_DATA_F",min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"),
    177                          unit, soc_i2c_devname(unit,devno),
    178                          dac_params[len].name,
    179                          dac_params[len].max,
    180                          dac_params[len].min,
    181                          dac_params[len].step));
    182         }
    183 	break;
    184 
    185     case I2C_DAC_IOC_SET_VOUT:
    186 	/* Set output voltage */
    187 	fval = *((I2C_DATA_T*)data);
    188         if (dac_params) {
    189             if ((fval < dac_params[len].min)||(fval > dac_params[len].max)){
    190                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    191                             (BSL_META_U(unit,
    192                                         "unit %d i2c %s: calibration/range error :"
    193                                         "requested=%"I2C_DATA_F" (max=%"I2C_DATA_F"),"
    194                                         "min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"),
    195                              unit, soc_i2c_devname(unit,devno),
    196                              fval, dac_params[len].max,
    197                              dac_params[len].min,
    198                              dac_params[len].step));
    199                 return SOC_E_PARAM;
    200             }
    201             /*
    202              * Core (A,B,PHY) : DACVAL  = VMax - VReq / Step
    203              * TurboRef: DACVAL = VReq - VMin / Step
    204              */
    205             if(dac_params[len].use_max)
    206                 tmp = ((dac_params[len].max - fval) / dac_params[len].step);
    207             else
    208                 tmp = ((fval - dac_params[len].min) / dac_params[len].step);
    209             dac = (uint16)tmp;
    210 
    211             dac &= LTC1427_VALID_BITS; /* Clear bits to make 10bit value */
    212 
    213             /* Show what we are doing, for now ... */
    214             LOG_VERBOSE(BSL_LS_SOC_COMMON,
    215                         (BSL_META_U(unit,
    216                                     "unit %d i2c %s: Set V_%s:"
    217                                     "request=%"I2C_DATA_F" dac=0x%x (max=%"I2C_DATA_F","
    218                                     "min=%"I2C_DATA_F",step=%"I2C_DATA_F")\n"),
    219                          unit, soc_i2c_devname(unit, devno),
    220                          dac_params[len].name,
    221                          fval,
    222                          dac,
    223                          dac_params[len].max,
    224                          dac_params[len].min,
    225                          dac_params[len].step));
    226             rv = ltc1427_write(unit, devno, 0, (uint8*)&dac, sizeof(short));
    227             /* Keep last value since DAC is write-only device */
    228             dac_params[len].dac_last_val = dac;
    229         }
    230 	break;
    231 
    232     default:
    233 	LOG_VERBOSE(BSL_LS_SOC_COMMON,
    234                     (BSL_META_U(unit,
    235                                 "unit %d i2c %s: ltc1427_ioctl: invalid opcode (%d)\n"),
    236                      unit, soc_i2c_devname(unit,devno),
    237                      opcode));
    238 	break;
    239     }
    240 
    241     return rv;
    242 }
    243 
    244 STATIC int
    245 ltc1427_init(int unit, int devno,
    246 	  void* data, int len)
    247 {
    248     dac_params = NULL;
    249 
    250     soc_i2c_devdesc_set(unit, devno, "Linear Technology LTC1427 DAC");
    251 
    252     return SOC_E_NONE;
    253 }
    254 
    255 /* LTC1427 Clock Chip Driver callout */
    256 i2c_driver_t _soc_i2c_ltc1427_driver = {
    257     0x0, 0x0, /* System assigned bytes */
    258     LTC1427_DEVICE_TYPE,
    259     ltc1427_read,
    260     ltc1427_write,
    261     ltc1427_ioctl,
    262     ltc1427_init,
    263     NULL,
    264 };