Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.13 213 lines 5.5 kB view raw
1/****************************************************************************** 2 * 3 * Name: sklm80.c 4 * Project: Gigabit Ethernet Adapters, TWSI-Module 5 * Version: $Revision: 1.22 $ 6 * Date: $Date: 2003/10/20 09:08:21 $ 7 * Purpose: Functions to access Voltage and Temperature Sensor (LM80) 8 * 9 ******************************************************************************/ 10 11/****************************************************************************** 12 * 13 * (C)Copyright 1998-2002 SysKonnect. 14 * (C)Copyright 2002-2003 Marvell. 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation; either version 2 of the License, or 19 * (at your option) any later version. 20 * 21 * The information in this file is provided "AS IS" without warranty. 22 * 23 ******************************************************************************/ 24 25/* 26 LM80 functions 27*/ 28#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) 29static const char SysKonnectFileId[] = 30 "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. "; 31#endif 32 33#include "h/skdrv1st.h" /* Driver Specific Definitions */ 34#include "h/lm80.h" 35#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ 36 37#ifdef SK_DIAG 38#define BREAK_OR_WAIT(pAC,IoC,Event) SkI2cWait(pAC,IoC,Event) 39#else /* nSK_DIAG */ 40#define BREAK_OR_WAIT(pAC,IoC,Event) break 41#endif /* nSK_DIAG */ 42 43#ifdef SK_DIAG 44/* 45 * read the register 'Reg' from the device 'Dev' 46 * 47 * return read error -1 48 * success the read value 49 */ 50int SkLm80RcvReg( 51SK_IOC IoC, /* Adapter Context */ 52int Dev, /* I2C device address */ 53int Reg) /* register to read */ 54{ 55 int Val = 0; 56 int TempExt; 57 58 /* Signal device number */ 59 if (SkI2cSndDev(IoC, Dev, I2C_WRITE)) { 60 return(-1); 61 } 62 63 if (SkI2cSndByte(IoC, Reg)) { 64 return(-1); 65 } 66 67 /* repeat start */ 68 if (SkI2cSndDev(IoC, Dev, I2C_READ)) { 69 return(-1); 70 } 71 72 switch (Reg) { 73 case LM80_TEMP_IN: 74 Val = (int)SkI2cRcvByte(IoC, 1); 75 76 /* First: correct the value: it might be negative */ 77 if ((Val & 0x80) != 0) { 78 /* Value is negative */ 79 Val = Val - 256; 80 } 81 Val = Val * SK_LM80_TEMP_LSB; 82 SkI2cStop(IoC); 83 84 TempExt = (int)SkLm80RcvReg(IoC, LM80_ADDR, LM80_TEMP_CTRL); 85 86 if (Val > 0) { 87 Val += ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); 88 } 89 else { 90 Val -= ((TempExt >> 7) * SK_LM80_TEMPEXT_LSB); 91 } 92 return(Val); 93 break; 94 case LM80_VT0_IN: 95 case LM80_VT1_IN: 96 case LM80_VT2_IN: 97 case LM80_VT3_IN: 98 Val = (int)SkI2cRcvByte(IoC, 1) * SK_LM80_VT_LSB; 99 break; 100 101 default: 102 Val = (int)SkI2cRcvByte(IoC, 1); 103 break; 104 } 105 106 SkI2cStop(IoC); 107 return(Val); 108} 109#endif /* SK_DIAG */ 110 111/* 112 * read a sensors value (LM80 specific) 113 * 114 * This function reads a sensors value from the I2C sensor chip LM80. 115 * The sensor is defined by its index into the sensors database in the struct 116 * pAC points to. 117 * 118 * Returns 1 if the read is completed 119 * 0 if the read must be continued (I2C Bus still allocated) 120 */ 121int SkLm80ReadSensor( 122SK_AC *pAC, /* Adapter Context */ 123SK_IOC IoC, /* I/O Context needed in level 1 and 2 */ 124SK_SENSOR *pSen) /* Sensor to be read */ 125{ 126 SK_I32 Value; 127 128 switch (pSen->SenState) { 129 case SK_SEN_IDLE: 130 /* Send address to ADDR register */ 131 SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0); 132 133 pSen->SenState = SK_SEN_VALUE ; 134 BREAK_OR_WAIT(pAC, IoC, I2C_READ); 135 136 case SK_SEN_VALUE: 137 /* Read value from data register */ 138 SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); 139 140 Value &= 0xff; /* only least significant byte is valid */ 141 142 /* Do NOT check the Value against the thresholds */ 143 /* Checking is done in the calling instance */ 144 145 if (pSen->SenType == SK_SEN_VOLT) { 146 /* Voltage sensor */ 147 pSen->SenValue = Value * SK_LM80_VT_LSB; 148 pSen->SenState = SK_SEN_IDLE ; 149 return(1); 150 } 151 152 if (pSen->SenType == SK_SEN_FAN) { 153 if (Value != 0 && Value != 0xff) { 154 /* Fan speed counter */ 155 pSen->SenValue = SK_LM80_FAN_FAKTOR/Value; 156 } 157 else { 158 /* Indicate Fan error */ 159 pSen->SenValue = 0; 160 } 161 pSen->SenState = SK_SEN_IDLE ; 162 return(1); 163 } 164 165 /* First: correct the value: it might be negative */ 166 if ((Value & 0x80) != 0) { 167 /* Value is negative */ 168 Value = Value - 256; 169 } 170 171 /* We have a temperature sensor and need to get the signed extension. 172 * For now we get the extension from the last reading, so in the normal 173 * case we won't see flickering temperatures. 174 */ 175 pSen->SenValue = (Value * SK_LM80_TEMP_LSB) + 176 (pSen->SenValue % SK_LM80_TEMP_LSB); 177 178 /* Send address to ADDR register */ 179 SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0); 180 181 pSen->SenState = SK_SEN_VALEXT ; 182 BREAK_OR_WAIT(pAC, IoC, I2C_READ); 183 184 case SK_SEN_VALEXT: 185 /* Read value from data register */ 186 SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); 187 Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */ 188 189 /* cut the LSB bit */ 190 pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) * 191 SK_LM80_TEMP_LSB); 192 193 if (pSen->SenValue < 0) { 194 /* Value negative: The bit value must be subtracted */ 195 pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB); 196 } 197 else { 198 /* Value positive: The bit value must be added */ 199 pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB); 200 } 201 202 pSen->SenState = SK_SEN_IDLE ; 203 return(1); 204 205 default: 206 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG); 207 return(1); 208 } 209 210 /* Not completed */ 211 return(0); 212} 213