1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
/*
* VIA VT82C686A/B hardware monitor chip
*
***************************************************************
* Before calling these routines, one must call method->Open() *
* After calling these routines, one must call method->Close() *
***************************************************************
*
VIA
Chip Temp Volt Fan SMBus IOport
via686a 3 5 2 yes yes
*
* by YRS
*/
#include "pci_pm.h"
#include "sensors.h"
/* external (global) data */
extern int smb_slave;
extern int pm_smb_detected;
extern LM_METHODS method_via, method_smb;
extern int numSMBSlave, canSMBSlave[128];
#define VIA_ADDR_START 0x50 /*0x50-0x5E*/
#define VIA_ADDR_END 0x5E
/* temp nr=0,1,2; volt nr=0,...4; fan nr=0,1 */
#define VIA686_TEMP(nr) (0x1F + (nr))
#define VIA686_VOLT(nr) (0x22 + (nr))
#define VIA686_FAN(nr) (0x29 + (nr))
#define VIA686_FANDIV 0x47
static int via686_probe(LM_METHODS *methods);
static float via686_temp(LM_METHODS *methods, int no);
static int via686_fanrpm(LM_METHODS *methods, int no);
static float via686_volt(LM_METHODS *methods, int no);
SENSOR via686 = {
"VIA Chip VT82C686A/B",
via686_probe,
via686_temp,
via686_volt,
via686_fanrpm
};
#define VIA_chkRegNum 5
/* Register checked for probing */
static int chkReg[] = {
0x40, 0x41, 0x42, 0x43,
0x44, 0x47, 0x49, 0x4B,
0x3F, 0x14, 0x1F, 0x20,
0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x29, 0x2B,
-1 };
/*
* return 0 if not probed
*/
static int via686_probe(LM_METHODS *method)
{
int n, save;
if (method != &method_via && method != &method_smb)
return 0;
if (pm_smb_detected != VIA686HWM && pm_smb_detected != VIA686SMB)
return 0;
save = smb_slave;
if (method == &method_smb) {
for (n = VIA_ADDR_START; n <= VIA_ADDR_END;) {
if (!(smb_slave = get_smb_slave(n, VIA_ADDR_END)))
goto ret0;
else {
if (chkReg_Probe(smb_slave, "Probing VIA686A/B chip:\n",
chkReg, method) >= VIA_chkRegNum)
goto ret1;
else
n = smb_slave + 2;
}
}
} else {
if (chkReg_Probe(0, "Probing VIA686A/B chip:\n",
chkReg, method) >= VIA_chkRegNum)
goto ret1;
}
ret0:
smb_slave = save;
return 0;
ret1:
if (method == &method_smb)
kill_smb_slave(smb_slave);
return 1;
}
static const float via686temp_tab[256] = {\
.00, .00, .00, .00, .00, .00, .00, .00,
.00, .00, .00, .00, .00, .00, .00,-50.00,
-48.00,-46.09,-44.26,-42.52,-40.86,-39.28,-37.78,-36.35,
-34.99,-33.70,-32.47,-31.31,-30.20,-29.15,-28.14,-27.18,
-26.27,-25.39,-24.55,-23.73,-22.95,-22.18,-21.44,-20.70,
-19.98,-19.27,-18.57,-17.87,-17.19,-16.51,-15.85,-15.20,
-14.56,-13.93,-13.32,-12.72,-12.14,-11.58,-11.03,-10.50,
-9.99, -9.50, -9.03, -8.57, -8.11, -7.67, -7.22, -6.77,
-6.31, -5.85, -5.37, -4.87, -4.36, -3.81, -3.24, -2.64,
-2.00, -1.33, -.65, .00, .59, 1.12, 1.60, 2.03,
2.42, 2.79, 3.12, 3.44, 3.75, 4.05, 4.35, 4.67,
4.99, 5.34, 5.71, 6.09, 6.49, 6.91, 7.34, 7.78,
8.23, 8.69, 9.15, 9.62, 10.09, 10.57, 11.04, 11.51,
11.98, 12.44, 12.90, 13.35, 13.80, 14.24, 14.68, 15.12,
15.55, 15.99, 16.42, 16.85, 17.27, 17.70, 18.13, 18.56,
18.99, 19.42, 19.85, 20.29, 20.72, 21.15, 21.59, 22.03,
22.47, 22.90, 23.34, 23.78, 24.22, 24.66, 25.10, 25.54,
25.99, 26.43, 26.87, 27.31, 27.75, 28.19, 28.63, 29.07,
29.51, 29.95, 30.38, 30.82, 31.25, 31.68, 32.11, 32.53,
32.96, 33.38, 33.80, 34.22, 34.63, 35.05, 35.48, 35.90,
36.33, 36.76, 37.20, 37.64, 38.09, 38.55, 39.02, 39.50,
39.99, 40.49, 41.00, 41.52, 42.06, 42.60, 43.15, 43.70,
44.27, 44.84, 45.41, 45.99, 46.57, 47.16, 47.75, 48.35,
48.94, 49.54, 50.13, 50.73, 51.33, 51.94, 52.55, 53.16,
53.78, 54.41, 55.04, 55.68, 56.32, 56.98, 57.64, 58.32,
59.00, 59.69, 60.40, 61.12, 61.85, 62.60, 63.36, 64.13,
64.93, 65.73, 66.56, 67.40, 68.26, 69.14, 70.05, 70.97,
71.91, 72.88, 73.86, 74.88, 75.92, 76.98, 78.08, 79.21,
80.36, 81.55, 82.78, 84.03, 85.33, 86.66, 88.04, 89.45,
90.90, 92.40, 93.94, 95.53, 97.16, 98.85,100.58,102.36,
104.19,106.07,108.01,110.00, .00, .00, .00, .00,
.00, .00, .00, .00, .00, .00, .00, .00
};
/*
* \retval 0xFFFF no sensor
* \retval other temperature
* no = 0,1,2,...
*/
static float via686_temp(LM_METHODS *method, int no)
{
if (no < 0 || 2 < no)
return 0xFFFF;
return via686temp_tab[method->Read(VIA686_TEMP(no))];
}
/*
* \retval 0x0000FFFF no sensor
* no = 0,1,2,...
*/
static float via686_volt(LM_METHODS *method, int no)
{
int n;
float fac;
if ( no < 0 || 4 < no )
return 0xFFFF;
switch (no) {
case 0:
case 1:
fac = 5. / 10512.;
break;
case 2:
fac = 5. / 7884.;
break;
case 3:
fac = 26. / 26280.;
break;
case 4:
fac = 63. / 26280.;
}
if ((n = method->Read(VIA686_VOLT(no))) <= 0x40)
n |= 0x100;
return (float) (n * 25 + 133) * fac;
}
/*
Controlling Fan Divisor: CR = 0x47.
highest two bits for fan2, next two bits for fan1
7 3 0
+-+-+-+-+-+-+-+-+ xx = 00,01,10,11 div1fac = 1,2,4,8
|y y|x x| VolID | yy = 00,01,10,11 div2fac = 1,2,4,8
+-+-+-+-+-+-+-+-+ initial values: xx=01, yy=01
*/
/*
* \retval 0x0000FFFF no sensor
* no = 0,1,2,...
*
* Clock is 22.5kHz (22,500 x 60 = 1350000 counts/minute)
*/
static int via686_fanrpm(LM_METHODS *method, int no)
{
int r, n;
static int div[2] = {1,1};
if (no < 0 || 1 < no)
return 0xFFFF;
n = method->Read(VIA686_FANDIV);
div[0] = (n >> 4) & 0x03;
div[1] = n >> 6;
r = method->Read(VIA686_FAN(no));
if (r == 0xFF) {
/* change divisor for the sake of next call ! */
if (div[no] < 3)
++(div[no]);
else
div[no] = 0;
r = (n & 0x0F) | (div[0] << 4) | (div[1] << 6);
method->Write(VIA686_FANDIV, r);
return 0xFFFF;
} else if (r == 0) {
return 0xFFFF;
}
return 1350000 / (r * (1 << div[no]));
}
|