1 /*
   2  * Copyright 2007-2013 Solarflare Communications Inc.  All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  *
  13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
  14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23  * SUCH DAMAGE.
  24  */
  25 
  26 #include "efsys.h"
  27 #include "efx.h"
  28 #include "efx_types.h"
  29 #include "efx_regs.h"
  30 #include "efx_impl.h"
  31 #include "lm87.h"
  32 #include "lm87_impl.h"
  33 
  34 #if EFSYS_OPT_MON_LM87
  35 
  36         __checkReturn   int
  37 lm87_reset(
  38         __in            efx_nic_t *enp)
  39 {
  40         uint8_t devid = enp->en_u.falcon.enu_mon_devid;
  41         efx_byte_t byte;
  42         int rc;
  43 
  44         /* Check we can communicate with the chip */
  45         if ((rc = falcon_i2c_check(enp, devid)) != 0)
  46                 goto fail1;
  47 
  48         /* Reset the chip */
  49         EFX_POPULATE_BYTE_1(byte, INIT, 1);
  50         if ((rc = falcon_i2c_write(enp, devid, CONFIG1_REG, (caddr_t)&byte,
  51             1)) != 0)
  52                 goto fail2;
  53 
  54         /* Check the company identifier and revision */
  55         if ((rc = falcon_i2c_read(enp, devid, ID_REG, (caddr_t)&byte, 1)) != 0)
  56                 goto fail3;
  57 
  58         if (EFX_BYTE_FIELD(byte, EFX_BYTE_0) != ID_DECODE) {
  59                 rc = ENODEV;
  60                 goto fail4;
  61         }
  62 
  63         if ((rc = falcon_i2c_read(enp, devid, REV_REG, (caddr_t)&byte, 1)) != 0)
  64                 goto fail5;
  65 
  66         if (EFX_BYTE_FIELD(byte, EFX_BYTE_0) != REV_DECODE) {
  67                 rc = ENODEV;
  68                 goto fail6;
  69         }
  70 
  71         return (0);
  72 
  73 fail6:
  74         EFSYS_PROBE(fail6);
  75 fail5:
  76         EFSYS_PROBE(fail5);
  77 fail4:
  78         EFSYS_PROBE(fail4);
  79 fail3:
  80         EFSYS_PROBE(fail3);
  81 fail2:
  82         EFSYS_PROBE(fail2);
  83 fail1:
  84         EFSYS_PROBE1(fail1, int, rc);
  85 
  86         return (rc);
  87 }
  88 
  89         __checkReturn   int
  90 lm87_reconfigure(
  91         __in            efx_nic_t *enp)
  92 {
  93         uint8_t devid = enp->en_u.falcon.enu_mon_devid;
  94         efx_byte_t byte;
  95         int rc;
  96 
  97         /* Configure the channel mode to select AIN1/2 rather than FAN1/2 */
  98         EFX_POPULATE_BYTE_2(byte, FAN1_AIN1, 1, FAN2_AIN2, 1);
  99         if ((rc = falcon_i2c_write(enp, devid, CHANNEL_MODE_REG, (caddr_t)&byte,
 100             1)) != 0)
 101                 goto fail1;
 102 
 103         /* Mask out all interrupts */
 104         EFX_SET_BYTE(byte);
 105         if ((rc = falcon_i2c_write(enp, devid, INTERRUPT_MASK1_REG,
 106             (caddr_t)&byte, 1)) != 0)
 107                 goto fail2;
 108         if ((rc = falcon_i2c_write(enp, devid, INTERRUPT_MASK2_REG,
 109             (caddr_t)&byte, 1)) != 0)
 110                 goto fail3;
 111 
 112         /* Start monitoring */
 113         EFX_POPULATE_BYTE_1(byte, START, 1);
 114         if ((rc = falcon_i2c_write(enp, devid, CONFIG1_REG, (caddr_t)&byte,
 115             1)) != 0)
 116                 goto fail4;
 117 
 118         return (0);
 119 
 120 fail4:
 121         EFSYS_PROBE(fail4);
 122 fail3:
 123         EFSYS_PROBE(fail3);
 124 fail2:
 125         EFSYS_PROBE(fail2);
 126 fail1:
 127         EFSYS_PROBE1(fail1, int, rc);
 128 
 129         return (rc);
 130 }
 131 
 132 #if EFSYS_OPT_MON_STATS
 133 
 134 #define LM87_STAT_SET(_enp, _mask, _value, _id, _rc)                    \
 135         do {                                                            \
 136                 uint8_t devid = enp->en_u.falcon.enu_mon_devid;              \
 137                 efx_mon_stat_value_t *value =                           \
 138                         (_value) + EFX_MON_STAT_ ## _id;                \
 139                 efx_byte_t byte;                                        \
 140                                                                         \
 141                 if (((_rc) = falcon_i2c_read((_enp), devid,             \
 142                     VALUE_ ## _id ## _REG, (caddr_t)&byte, 1)) == 0) {      \
 143                         uint8_t val = EFX_BYTE_FIELD(byte, EFX_BYTE_0); \
 144                         value->emsv_value = (uint16_t)val;           \
 145                         value->emsv_state = 0;                               \
 146                 }                                                       \
 147                                                                         \
 148                 (_mask) |= (1 << (EFX_MON_STAT_ ## _id));         \
 149                 _NOTE(CONSTANTCONDITION)                                \
 150         } while (B_FALSE)
 151 
 152         __checkReturn                   int
 153 lm87_stats_update(
 154         __in                            efx_nic_t *enp,
 155         __in                            efsys_mem_t *esmp,
 156         __out_ecount(EFX_MON_NSTATS)    efx_mon_stat_value_t *values)
 157 {
 158         uint32_t mask = 0;
 159         int rc;
 160 
 161         _NOTE(ARGUNUSED(esmp))
 162 
 163         LM87_STAT_SET(enp, mask, values, 2_5V, rc);
 164         if (rc != 0)
 165                 goto fail1;
 166 
 167         LM87_STAT_SET(enp, mask, values, VCCP1, rc);
 168         if (rc != 0)
 169                 goto fail2;
 170 
 171         LM87_STAT_SET(enp, mask, values, VCC, rc);
 172         if (rc != 0)
 173                 goto fail3;
 174 
 175         LM87_STAT_SET(enp, mask, values, 5V, rc);
 176         if (rc != 0)
 177                 goto fail4;
 178 
 179         LM87_STAT_SET(enp, mask, values, 12V, rc);
 180         if (rc != 0)
 181                 goto fail5;
 182 
 183         LM87_STAT_SET(enp, mask, values, VCCP2, rc);
 184         if (rc != 0)
 185                 goto fail6;
 186 
 187         LM87_STAT_SET(enp, mask, values, EXT_TEMP, rc);
 188         if (rc != 0)
 189                 goto fail7;
 190 
 191         LM87_STAT_SET(enp, mask, values, INT_TEMP, rc);
 192         if (rc != 0)
 193                 goto fail8;
 194 
 195         LM87_STAT_SET(enp, mask, values, AIN1, rc);
 196         if (rc != 0)
 197                 goto fail9;
 198 
 199         LM87_STAT_SET(enp, mask, values, AIN2, rc);
 200         if (rc != 0)
 201                 goto fail10;
 202 
 203         EFSYS_ASSERT3U(mask, ==, LM87_STAT_MASK);
 204 
 205         return (0);
 206 
 207 fail10:
 208         EFSYS_PROBE(fail10);
 209 fail9:
 210         EFSYS_PROBE(fail9);
 211 fail8:
 212         EFSYS_PROBE(fail8);
 213 fail7:
 214         EFSYS_PROBE(fail7);
 215 fail6:
 216         EFSYS_PROBE(fail6);
 217 fail5:
 218         EFSYS_PROBE(fail5);
 219 fail4:
 220         EFSYS_PROBE(fail4);
 221 fail3:
 222         EFSYS_PROBE(fail3);
 223 fail2:
 224         EFSYS_PROBE(fail2);
 225 fail1:
 226         EFSYS_PROBE1(fail1, int, rc);
 227 
 228         return (rc);
 229 }
 230 #endif  /* EFSYS_OPT_MON_STATS */
 231 
 232 #endif  /* EFSYS_OPT_MON_LM87 */