blob: 894cc67cbdbf38c46bef3c1e090b0c80be583b50 [file] [log] [blame]
wdenkeb20ad32003-09-05 23:19:14 +00001/******************************************************************************
2 *
3 * Name: ski2c.c
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.57 $
6 * Date: $Date: 2003/01/28 09:17:38 $
7 * Purpose: Functions to access Voltage and Temperature Sensor
8 *
9 ******************************************************************************/
10
11/******************************************************************************
12 *
13 * (C)Copyright 1998-2003 SysKonnect GmbH.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * The information in this file is provided "AS IS" without warranty.
21 *
22 ******************************************************************************/
23
24/******************************************************************************
25 *
26 * History:
27 *
28 * $Log: ski2c.c,v $
29 * Revision 1.57 2003/01/28 09:17:38 rschmidt
30 * Fixed handling for sensors on YUKON Fiber.
31 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000032 *
wdenkeb20ad32003-09-05 23:19:14 +000033 * Revision 1.56 2002/12/19 14:20:41 rschmidt
34 * Added debugging code in SkI2cWait().
35 * Replaced all I2C-write operations with function SkI2cWrite().
36 * Fixed compiler warning because of uninitialized 'Time' in SkI2cEvent().
37 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000038 *
wdenkeb20ad32003-09-05 23:19:14 +000039 * Revision 1.55 2002/10/15 07:23:55 rschmidt
40 * Added setting of the GIYukon32Bit bool variable to distinguish
41 * 32-bit adapters.
42 * Editorial changes (TWSI).
wdenk9c53f402003-10-15 23:53:47 +000043 *
wdenkeb20ad32003-09-05 23:19:14 +000044 * Revision 1.54 2002/08/13 09:05:06 rschmidt
45 * Added new thresholds if VAUX is not available (GIVauxAvail).
46 * Merged defines for PHY PLL 3V3 voltage (A and B).
47 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000048 *
wdenkeb20ad32003-09-05 23:19:14 +000049 * Revision 1.53 2002/08/08 11:04:53 rwahl
50 * Added missing comment for revision 1.51
wdenk9c53f402003-10-15 23:53:47 +000051 *
wdenkeb20ad32003-09-05 23:19:14 +000052 * Revision 1.52 2002/08/08 10:09:02 jschmalz
53 * Sensor init state caused wrong error log entry
wdenk9c53f402003-10-15 23:53:47 +000054 *
wdenkeb20ad32003-09-05 23:19:14 +000055 * Revision 1.51 2002/08/06 09:43:03 jschmalz
56 * Extensions and changes for Yukon
wdenk9c53f402003-10-15 23:53:47 +000057 *
wdenkeb20ad32003-09-05 23:19:14 +000058 * Revision 1.50 2002/08/02 12:09:22 rschmidt
59 * Added support for YUKON sensors.
60 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000061 *
wdenkeb20ad32003-09-05 23:19:14 +000062 * Revision 1.49 2002/07/30 11:07:52 rschmidt
63 * Replaced MaxSens init by update for Copper in SkI2cInit1(),
64 * because it was already initialized in SkI2cInit0().
65 * Editorial changes.
wdenk9c53f402003-10-15 23:53:47 +000066 *
wdenkeb20ad32003-09-05 23:19:14 +000067 * Revision 1.48 2001/08/16 12:44:33 afischer
68 * LM80 sensor init values corrected
wdenk9c53f402003-10-15 23:53:47 +000069 *
wdenkeb20ad32003-09-05 23:19:14 +000070 * Revision 1.47 2001/04/05 11:38:09 rassmann
71 * Set SenState to idle in SkI2cWaitIrq().
72 * Changed error message in SkI2cWaitIrq().
wdenk9c53f402003-10-15 23:53:47 +000073 *
wdenkeb20ad32003-09-05 23:19:14 +000074 * Revision 1.46 2001/04/02 14:03:35 rassmann
75 * Changed pAC to IoC in SK_IN32().
wdenk9c53f402003-10-15 23:53:47 +000076 *
wdenkeb20ad32003-09-05 23:19:14 +000077 * Revision 1.45 2001/03/21 12:12:49 rassmann
78 * Resetting I2C_READY interrupt in SkI2cInit1().
wdenk9c53f402003-10-15 23:53:47 +000079 *
wdenkeb20ad32003-09-05 23:19:14 +000080 * Revision 1.44 2000/08/07 15:49:03 gklug
81 * Fix: SK_INFAST only in NetWare driver.
wdenk9c53f402003-10-15 23:53:47 +000082 *
wdenkeb20ad32003-09-05 23:19:14 +000083 * Revision 1.43 2000/08/03 14:28:17 rassmann
84 * Added function to wait for I2C being ready before resetting the board.
85 * Replaced one duplicate "out of range" message with correct one.
wdenk9c53f402003-10-15 23:53:47 +000086 *
wdenkeb20ad32003-09-05 23:19:14 +000087 * Revision 1.42 1999/11/22 13:35:12 cgoos
88 * Changed license header to GPL.
wdenk9c53f402003-10-15 23:53:47 +000089 *
wdenkeb20ad32003-09-05 23:19:14 +000090 * Revision 1.41 1999/09/14 14:11:30 malthoff
91 * The 1000BT Dual Link adapter has got only one Fan.
92 * The second Fan has been removed.
wdenk9c53f402003-10-15 23:53:47 +000093 *
wdenkeb20ad32003-09-05 23:19:14 +000094 * Revision 1.40 1999/05/27 13:37:27 malthoff
95 * Set divisor of 1 for fan count calculation.
wdenk9c53f402003-10-15 23:53:47 +000096 *
wdenkeb20ad32003-09-05 23:19:14 +000097 * Revision 1.39 1999/05/20 14:54:43 malthoff
98 * I2c.DummyReads is not used in Diagnostics.
wdenk9c53f402003-10-15 23:53:47 +000099 *
wdenkeb20ad32003-09-05 23:19:14 +0000100 * Revision 1.38 1999/05/20 09:20:56 cgoos
101 * Changes for 1000Base-T (up to 9 sensors and fans).
wdenk9c53f402003-10-15 23:53:47 +0000102 *
wdenkeb20ad32003-09-05 23:19:14 +0000103 * Revision 1.37 1999/03/25 15:11:36 gklug
104 * fix: reset error flag if sensor reads correct value
wdenk9c53f402003-10-15 23:53:47 +0000105 *
wdenkeb20ad32003-09-05 23:19:14 +0000106 * Revision 1.36 1999/01/07 14:11:16 gklug
107 * fix: break added
wdenk9c53f402003-10-15 23:53:47 +0000108 *
wdenkeb20ad32003-09-05 23:19:14 +0000109 * Revision 1.35 1999/01/05 15:31:49 gklug
110 * fix: CLEAR STAT command is now added correctly
wdenk9c53f402003-10-15 23:53:47 +0000111 *
wdenkeb20ad32003-09-05 23:19:14 +0000112 * Revision 1.34 1998/12/01 13:45:16 gklug
113 * fix: introduced Init level, because we don't need reinits
wdenk9c53f402003-10-15 23:53:47 +0000114 *
wdenkeb20ad32003-09-05 23:19:14 +0000115 * Revision 1.33 1998/11/09 14:54:25 malthoff
116 * Modify I2C Transfer Timeout handling for Diagnostics.
wdenk9c53f402003-10-15 23:53:47 +0000117 *
wdenkeb20ad32003-09-05 23:19:14 +0000118 * Revision 1.32 1998/11/03 06:54:35 gklug
119 * fix: Need dummy reads at the beginning to init sensors
120 *
121 * Revision 1.31 1998/11/03 06:42:42 gklug
122 * fix: select correctVIO range only if between warning levels
wdenk9c53f402003-10-15 23:53:47 +0000123 *
wdenkeb20ad32003-09-05 23:19:14 +0000124 * Revision 1.30 1998/11/02 07:36:53 gklug
125 * fix: Error should not include WARNING message
wdenk9c53f402003-10-15 23:53:47 +0000126 *
wdenkeb20ad32003-09-05 23:19:14 +0000127 * Revision 1.29 1998/10/30 15:07:43 malthoff
128 * Disable 'I2C does not compelete' error log for diagnostics.
wdenk9c53f402003-10-15 23:53:47 +0000129 *
wdenkeb20ad32003-09-05 23:19:14 +0000130 * Revision 1.28 1998/10/22 09:48:11 gklug
131 * fix: SysKonnectFileId typo
wdenk9c53f402003-10-15 23:53:47 +0000132 *
wdenkeb20ad32003-09-05 23:19:14 +0000133 * Revision 1.27 1998/10/20 09:59:46 gklug
134 * add: parameter to SkOsGetTime
wdenk9c53f402003-10-15 23:53:47 +0000135 *
wdenkeb20ad32003-09-05 23:19:14 +0000136 * Revision 1.26 1998/10/09 06:10:59 malthoff
137 * Remove ID_sccs by SysKonnectFileId.
wdenk9c53f402003-10-15 23:53:47 +0000138 *
wdenkeb20ad32003-09-05 23:19:14 +0000139 * Revision 1.25 1998/09/08 12:40:26 gklug
140 * fix: syntax error in if clause
wdenk9c53f402003-10-15 23:53:47 +0000141 *
wdenkeb20ad32003-09-05 23:19:14 +0000142 * Revision 1.24 1998/09/08 12:19:42 gklug
143 * chg: INIT Level checking
wdenk9c53f402003-10-15 23:53:47 +0000144 *
wdenkeb20ad32003-09-05 23:19:14 +0000145 * Revision 1.23 1998/09/08 07:37:20 gklug
146 * fix: log error if PCI_IO voltage sensor could not be initialized
wdenk9c53f402003-10-15 23:53:47 +0000147 *
wdenkeb20ad32003-09-05 23:19:14 +0000148 * Revision 1.22 1998/09/04 08:30:03 malthoff
149 * Bugfixes during SK_DIAG testing:
150 * - correct NS2BCLK() macro
151 * - correct SkI2cSndDev()
152 * - correct SkI2cWait() loop waiting for an event
wdenk9c53f402003-10-15 23:53:47 +0000153 *
wdenkeb20ad32003-09-05 23:19:14 +0000154 * Revision 1.21 1998/08/27 14:46:01 gklug
155 * chg: if-then-else replaced by switch
156 *
157 * Revision 1.20 1998/08/27 14:40:07 gklug
158 * test: integral types
wdenk9c53f402003-10-15 23:53:47 +0000159 *
wdenkeb20ad32003-09-05 23:19:14 +0000160 * Revision 1.19 1998/08/25 07:51:54 gklug
161 * fix: typos for compiling
wdenk9c53f402003-10-15 23:53:47 +0000162 *
wdenkeb20ad32003-09-05 23:19:14 +0000163 * Revision 1.18 1998/08/25 06:12:24 gklug
164 * add: count errors and warnings
165 * fix: check not the sensor state but the ErrFlag!
wdenk9c53f402003-10-15 23:53:47 +0000166 *
wdenkeb20ad32003-09-05 23:19:14 +0000167 * Revision 1.17 1998/08/25 05:56:48 gklug
168 * add: CheckSensor function
wdenk9c53f402003-10-15 23:53:47 +0000169 *
wdenkeb20ad32003-09-05 23:19:14 +0000170 * Revision 1.16 1998/08/20 11:41:10 gklug
171 * chg: omit STRCPY macro by using char * as Sensor Description
wdenk9c53f402003-10-15 23:53:47 +0000172 *
wdenkeb20ad32003-09-05 23:19:14 +0000173 * Revision 1.15 1998/08/20 11:37:35 gklug
174 * chg: change Ioc to IoC
wdenk9c53f402003-10-15 23:53:47 +0000175 *
wdenkeb20ad32003-09-05 23:19:14 +0000176 * Revision 1.14 1998/08/20 11:32:52 gklug
177 * fix: Para compile error
wdenk9c53f402003-10-15 23:53:47 +0000178 *
wdenkeb20ad32003-09-05 23:19:14 +0000179 * Revision 1.13 1998/08/20 11:27:41 gklug
180 * fix: Compile bugs with new awrning constants
wdenk9c53f402003-10-15 23:53:47 +0000181 *
wdenkeb20ad32003-09-05 23:19:14 +0000182 * Revision 1.12 1998/08/20 08:53:05 gklug
183 * fix: compiler errors
184 * add: Threshold values
wdenk9c53f402003-10-15 23:53:47 +0000185 *
wdenkeb20ad32003-09-05 23:19:14 +0000186 * Revision 1.11 1998/08/19 12:39:22 malthoff
187 * Compiler Fix: Some names have changed.
wdenk9c53f402003-10-15 23:53:47 +0000188 *
wdenkeb20ad32003-09-05 23:19:14 +0000189 * Revision 1.10 1998/08/19 12:20:56 gklug
190 * fix: remove struct from C files (see CCC)
wdenk9c53f402003-10-15 23:53:47 +0000191 *
wdenkeb20ad32003-09-05 23:19:14 +0000192 * Revision 1.9 1998/08/19 06:28:46 malthoff
193 * SkOsGetTime returns SK_U64 now.
wdenk9c53f402003-10-15 23:53:47 +0000194 *
wdenkeb20ad32003-09-05 23:19:14 +0000195 * Revision 1.8 1998/08/17 13:53:33 gklug
196 * fix: Parameter of event function and its result
wdenk9c53f402003-10-15 23:53:47 +0000197 *
wdenkeb20ad32003-09-05 23:19:14 +0000198 * Revision 1.7 1998/08/17 07:02:15 malthoff
199 * Modify the functions for accessing the I2C SW Registers.
200 * Modify SkI2cWait().
201 * Put Lm80RcvReg into sklm80.c
202 * Remove Compiler Errors.
wdenk9c53f402003-10-15 23:53:47 +0000203 *
wdenkeb20ad32003-09-05 23:19:14 +0000204 * Revision 1.6 1998/08/14 07:13:20 malthoff
205 * remove pAc with pAC
206 * remove smc with pAC
207 * change names to new convention
208 *
209 * Revision 1.5 1998/08/14 06:24:49 gklug
210 * add: init level 1 and 2
211 *
212 * Revision 1.4 1998/08/12 14:31:12 gklug
213 * add: error log for unknown event
214 *
215 * Revision 1.3 1998/08/12 13:37:04 gklug
216 * add: Init 0 function
217 *
218 * Revision 1.2 1998/08/11 07:27:15 gklug
219 * add: functions of the interface
220 * adapt rest of source to C coding Conventions
221 * rmv: unnecessary code taken from Mona Lisa
222 *
223 * Revision 1.1 1998/06/19 14:28:43 malthoff
224 * Created. Sources taken from ML Projekt.
225 * Sources have to be reworked for GE.
226 *
227 *
228 ******************************************************************************/
229
230
wdenkde887eb2003-09-10 18:20:28 +0000231#include <config.h>
232
wdenkeb20ad32003-09-05 23:19:14 +0000233/*
234 * I2C Protocol
235 */
236static const char SysKonnectFileId[] =
237 "$Id: ski2c.c,v 1.57 2003/01/28 09:17:38 rschmidt Exp $";
238
239#include "h/skdrv1st.h" /* Driver Specific Definitions */
240#include "h/lm80.h"
241#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
242
243#ifdef __C2MAN__
244/*
245 I2C protocol implementation.
246
247 General Description:
248
249 The I2C protocol is used for the temperature sensors and for
250 the serial EEPROM which hold the configuration.
251
252 This file covers functions that allow to read write and do
253 some bulk requests a specified I2C address.
254
255 The Genesis has 2 I2C buses. One for the EEPROM which holds
256 the VPD Data and one for temperature and voltage sensor.
257 The following picture shows the I2C buses, I2C devices and
258 their control registers.
259
260 Note: The VPD functions are in skvpd.c
261.
262. PCI Config I2C Bus for VPD Data:
263.
264. +------------+
265. | VPD EEPROM |
266. +------------+
267. |
268. | <-- I2C
269. |
270. +-----------+-----------+
271. | |
272. +-----------------+ +-----------------+
273. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG |
274. +-----------------+ +-----------------+
275.
276.
277. I2C Bus for LM80 sensor:
278.
279. +-----------------+
280. | Temperature and |
281. | Voltage Sensor |
Wolfgang Denka1be4762008-05-20 16:00:29 +0200282. | LM80 |
wdenkeb20ad32003-09-05 23:19:14 +0000283. +-----------------+
284. |
285. |
286. I2C --> |
287. |
288. +----+
289. +-------------->| OR |<--+
290. | +----+ |
291. +------+------+ |
292. | | |
293. +--------+ +--------+ +----------+
294. | B2_I2C | | B2_I2C | | B2_I2C |
295. | _CTRL | | _DATA | | _SW |
296. +--------+ +--------+ +----------+
297.
298 The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
299 and B2_I2C_DATA registers.
300 For driver software it is recommended to use the I2C control and
301 data register, because I2C bus timing is done by the ASIC and
302 an interrupt may be received when the I2C request is completed.
303
304 Clock Rate Timing: MIN MAX generated by
305 VPD EEPROM: 50 kHz 100 kHz HW
306 LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW
307 LM80 over B2_I2C_SW register 0 400 kHz SW
308
309 Note: The clock generated by the hardware is dependend on the
310 PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
311 clock is 50 kHz.
312 */
313intro()
314{}
315#endif
316
317#ifdef SK_DIAG
318/*
319 * I2C Fast Mode timing values used by the LM80.
320 * If new devices are added to the I2C bus the timing values have to be checked.
321 */
322#ifndef I2C_SLOW_TIMING
323#define T_CLK_LOW 1300L /* clock low time in ns */
Wolfgang Denka1be4762008-05-20 16:00:29 +0200324#define T_CLK_HIGH 600L /* clock high time in ns */
wdenkeb20ad32003-09-05 23:19:14 +0000325#define T_DATA_IN_SETUP 100L /* data in Set-up Time */
326#define T_START_HOLD 600L /* start condition hold time */
327#define T_START_SETUP 600L /* start condition Set-up time */
328#define T_STOP_SETUP 600L /* stop condition Set-up time */
329#define T_BUS_IDLE 1300L /* time the bus must free after Tx */
330#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */
331#else /* I2C_SLOW_TIMING */
332/* I2C Standard Mode Timing */
333#define T_CLK_LOW 4700L /* clock low time in ns */
334#define T_CLK_HIGH 4000L /* clock high time in ns */
335#define T_DATA_IN_SETUP 250L /* data in Set-up Time */
336#define T_START_HOLD 4000L /* start condition hold time */
337#define T_START_SETUP 4700L /* start condition Set-up time */
338#define T_STOP_SETUP 4000L /* stop condition Set-up time */
339#define T_BUS_IDLE 4700L /* time the bus must free after Tx */
340#endif /* !I2C_SLOW_TIMING */
341
342#define NS2BCLK(x) (((x)*125)/10000)
343
344/*
345 * I2C Wire Operations
346 *
347 * About I2C_CLK_LOW():
348 *
349 * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
350 * clock to low, to prevent the ASIC and the I2C data client from driving the
351 * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
352 * send an 'ACK'). See also Concentrator Bugreport No. 10192.
353 */
354#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA)
355#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA)
356#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
357#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
358#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK)
359#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
360#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK)
361
362#define NS2CLKT(x) ((x*125L)/10000)
363
364/*--------------- I2C Interface Register Functions --------------- */
365
366/*
367 * sending one bit
368 */
369void SkI2cSndBit(
370SK_IOC IoC, /* I/O Context */
371SK_U8 Bit) /* Bit to send */
372{
373 I2C_DATA_OUT(IoC);
374 if (Bit) {
375 I2C_DATA_HIGH(IoC);
376 }
377 else {
378 I2C_DATA_LOW(IoC);
379 }
380 SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
381 I2C_CLK_HIGH(IoC);
382 SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
383 I2C_CLK_LOW(IoC);
384} /* SkI2cSndBit*/
385
386
387/*
388 * Signal a start to the I2C Bus.
389 *
390 * A start is signaled when data goes to low in a high clock cycle.
391 *
392 * Ends with Clock Low.
393 *
394 * Status: not tested
395 */
396void SkI2cStart(
397SK_IOC IoC) /* I/O Context */
398{
399 /* Init data and Clock to output lines */
400 /* Set Data high */
401 I2C_DATA_OUT(IoC);
402 I2C_DATA_HIGH(IoC);
403 /* Set Clock high */
404 I2C_CLK_HIGH(IoC);
405
406 SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
407
408 /* Set Data Low */
409 I2C_DATA_LOW(IoC);
410
411 SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
412
413 /* Clock low without Data to Input */
414 I2C_START_COND(IoC);
415
416 SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
417} /* SkI2cStart */
418
419
420void SkI2cStop(
421SK_IOC IoC) /* I/O Context */
422{
423 /* Init data and Clock to output lines */
424 /* Set Data low */
425 I2C_DATA_OUT(IoC);
426 I2C_DATA_LOW(IoC);
427
428 SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
429
430 /* Set Clock high */
431 I2C_CLK_HIGH(IoC);
432
433 SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
434
435 /*
436 * Set Data High: Do it by setting the Data Line to Input.
437 * Because of a pull up resistor the Data Line
438 * floods to high.
439 */
440 I2C_DATA_IN(IoC);
441
442 /*
443 * When I2C activity is stopped
444 * o DATA should be set to input and
445 * o CLOCK should be set to high!
446 */
447 SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
448} /* SkI2cStop */
449
450
451/*
452 * Receive just one bit via the I2C bus.
453 *
454 * Note: Clock must be set to LOW before calling this function.
455 *
456 * Returns The received bit.
457 */
458int SkI2cRcvBit(
459SK_IOC IoC) /* I/O Context */
460{
461 int Bit;
462 SK_U8 I2cSwCtrl;
463
464 /* Init data as input line */
465 I2C_DATA_IN(IoC);
466
467 SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
468
469 I2C_CLK_HIGH(IoC);
470
471 SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
472
473 SK_I2C_GET_SW(IoC, &I2cSwCtrl);
wdenk9c53f402003-10-15 23:53:47 +0000474
wdenkeb20ad32003-09-05 23:19:14 +0000475 Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
476
477 I2C_CLK_LOW(IoC);
478 SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
479
480 return(Bit);
481} /* SkI2cRcvBit */
482
483
484/*
485 * Receive an ACK.
486 *
487 * returns 0 If acknowledged
488 * 1 in case of an error
489 */
490int SkI2cRcvAck(
491SK_IOC IoC) /* I/O Context */
492{
493 /*
494 * Received bit must be zero.
495 */
496 return(SkI2cRcvBit(IoC) != 0);
497} /* SkI2cRcvAck */
498
499
500/*
501 * Send an NACK.
502 */
503void SkI2cSndNAck(
504SK_IOC IoC) /* I/O Context */
505{
506 /*
507 * Received bit must be zero.
508 */
509 SkI2cSndBit(IoC, 1);
510} /* SkI2cSndNAck */
511
512
513/*
514 * Send an ACK.
515 */
516void SkI2cSndAck(
517SK_IOC IoC) /* I/O Context */
518{
519 /*
520 * Received bit must be zero.
521 *
522 */
523 SkI2cSndBit(IoC, 0);
524} /* SkI2cSndAck */
525
526
527/*
528 * Send one byte to the I2C device and wait for ACK.
529 *
530 * Return acknowleged status.
531 */
532int SkI2cSndByte(
533SK_IOC IoC, /* I/O Context */
534int Byte) /* byte to send */
535{
536 int i;
537
538 for (i = 0; i < 8; i++) {
539 if (Byte & (1<<(7-i))) {
540 SkI2cSndBit(IoC, 1);
541 }
542 else {
543 SkI2cSndBit(IoC, 0);
544 }
545 }
546
547 return(SkI2cRcvAck(IoC));
548} /* SkI2cSndByte */
549
550
551/*
552 * Receive one byte and ack it.
553 *
554 * Return byte.
555 */
556int SkI2cRcvByte(
557SK_IOC IoC, /* I/O Context */
558int Last) /* Last Byte Flag */
559{
560 int i;
561 int Byte = 0;
562
563 for (i = 0; i < 8; i++) {
564 Byte <<= 1;
565 Byte |= SkI2cRcvBit(IoC);
566 }
567
568 if (Last) {
569 SkI2cSndNAck(IoC);
570 }
571 else {
572 SkI2cSndAck(IoC);
573 }
574
575 return(Byte);
576} /* SkI2cRcvByte */
577
578
579/*
580 * Start dialog and send device address
581 *
582 * Return 0 if acknowleged, 1 in case of an error
583 */
584int SkI2cSndDev(
585SK_IOC IoC, /* I/O Context */
586int Addr, /* Device Address */
587int Rw) /* Read / Write Flag */
588{
589 SkI2cStart(IoC);
590 Rw = ~Rw;
591 Rw &= I2C_WRITE;
592 return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
593} /* SkI2cSndDev */
594
595#endif /* SK_DIAG */
596
597/*----------------- I2C CTRL Register Functions ----------*/
598
599/*
600 * waits for a completion of an I2C transfer
601 *
602 * returns 0: success, transfer completes
603 * 1: error, transfer does not complete, I2C transfer
604 * killed, wait loop terminated.
605 */
606int SkI2cWait(
607SK_AC *pAC, /* Adapter Context */
608SK_IOC IoC, /* I/O Context */
609int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */
610{
611 SK_U64 StartTime;
612 SK_U64 CurrentTime;
613 SK_U32 I2cCtrl;
614
615 StartTime = SkOsGetTime(pAC);
wdenk9c53f402003-10-15 23:53:47 +0000616
wdenkeb20ad32003-09-05 23:19:14 +0000617 do {
618 CurrentTime = SkOsGetTime(pAC);
619
620 if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
wdenk9c53f402003-10-15 23:53:47 +0000621
wdenkeb20ad32003-09-05 23:19:14 +0000622 SK_I2C_STOP(IoC);
623#ifndef SK_DIAG
624 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
625#endif /* !SK_DIAG */
626 return(1);
627 }
wdenk9c53f402003-10-15 23:53:47 +0000628
wdenkeb20ad32003-09-05 23:19:14 +0000629 SK_I2C_GET_CTL(IoC, &I2cCtrl);
630
631#ifdef xYUKON_DBG
632 printf("StartTime=%lu, CurrentTime=%lu\n",
633 StartTime, CurrentTime);
634 if (kbhit()) {
635 return(1);
636 }
637#endif /* YUKON_DBG */
wdenk9c53f402003-10-15 23:53:47 +0000638
wdenkeb20ad32003-09-05 23:19:14 +0000639 } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
640
641 return(0);
642} /* SkI2cWait */
643
644
645/*
646 * waits for a completion of an I2C transfer
647 *
648 * Returns
649 * Nothing
650 */
651void SkI2cWaitIrq(
652SK_AC *pAC, /* Adapter Context */
653SK_IOC IoC) /* I/O Context */
654{
655 SK_SENSOR *pSen;
656 SK_U64 StartTime;
657 SK_U32 IrqSrc;
658
659 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
660
661 if (pSen->SenState == SK_SEN_IDLE) {
662 return;
663 }
664
665 StartTime = SkOsGetTime(pAC);
666 do {
667 if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
668 SK_I2C_STOP(IoC);
669#ifndef SK_DIAG
670 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
671#endif /* !SK_DIAG */
672 return;
673 }
674 SK_IN32(IoC, B0_ISRC, &IrqSrc);
675 } while ((IrqSrc & IS_I2C_READY) == 0);
676
677 pSen->SenState = SK_SEN_IDLE;
678 return;
679} /* SkI2cWaitIrq */
680
681/*
682 * writes a single byte or 4 bytes into the I2C device
683 *
684 * returns 0: success
685 * 1: error
686 */
687int SkI2cWrite(
688SK_AC *pAC, /* Adapter Context */
689SK_IOC IoC, /* I/O Context */
690SK_U32 I2cData, /* I2C Data to write */
691int I2cDev, /* I2C Device Address */
692int I2cReg, /* I2C Device Register Address */
693int I2cBurst) /* I2C Burst Flag */
694{
695 SK_OUT32(IoC, B2_I2C_DATA, I2cData);
696 SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cReg, I2cBurst);
wdenk9c53f402003-10-15 23:53:47 +0000697
wdenkeb20ad32003-09-05 23:19:14 +0000698 return(SkI2cWait(pAC, IoC, I2C_WRITE));
699} /* SkI2cWrite*/
700
701
702#ifdef SK_DIAG
703
704/*
705 * reads a single byte or 4 bytes from the I2C device
706 *
707 * returns the word read
708 */
709SK_U32 SkI2cRead(
710SK_AC *pAC, /* Adapter Context */
711SK_IOC IoC, /* I/O Context */
712int I2cDev, /* I2C Device Address */
713int I2cReg, /* I2C Device Register Address */
714int I2cBurst) /* I2C Burst Flag */
715{
716 SK_U32 Data;
717
718 SK_OUT32(IoC, B2_I2C_DATA, 0);
719 SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cReg, I2cBurst);
wdenk9c53f402003-10-15 23:53:47 +0000720
wdenkeb20ad32003-09-05 23:19:14 +0000721 if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
722 w_print("%s\n", SKERR_I2C_E002MSG);
723 }
wdenk9c53f402003-10-15 23:53:47 +0000724
wdenkeb20ad32003-09-05 23:19:14 +0000725 SK_IN32(IoC, B2_I2C_DATA, &Data);
726 return(Data);
727} /* SkI2cRead */
728
729#endif /* SK_DIAG */
730
731
732/*
733 * read a sensor's value
734 *
735 * This function reads a sensor's value from the I2C sensor chip. The sensor
736 * is defined by its index into the sensors database in the struct pAC points
737 * to.
738 * Returns
739 * 1 if the read is completed
740 * 0 if the read must be continued (I2C Bus still allocated)
741 */
742int SkI2cReadSensor(
743SK_AC *pAC, /* Adapter Context */
744SK_IOC IoC, /* I/O Context */
745SK_SENSOR *pSen) /* Sensor to be read */
746{
747 if (pSen->SenRead != NULL) {
wdenk9c53f402003-10-15 23:53:47 +0000748 return((*pSen->SenRead)(pAC, IoC, pSen));
wdenkeb20ad32003-09-05 23:19:14 +0000749 }
750 else
wdenk9c53f402003-10-15 23:53:47 +0000751 return(0); /* no success */
wdenkeb20ad32003-09-05 23:19:14 +0000752} /* SkI2cReadSensor*/
753
754/*
755 * Do the Init state 0 initialization
756 */
757static int SkI2cInit0(
758SK_AC *pAC) /* Adapter Context */
759{
760 int i;
761
762 /* Begin with first sensor */
763 pAC->I2c.CurrSens = 0;
wdenk9c53f402003-10-15 23:53:47 +0000764
wdenkeb20ad32003-09-05 23:19:14 +0000765 /* Begin with timeout control for state machine */
766 pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE;
wdenk9c53f402003-10-15 23:53:47 +0000767
wdenkeb20ad32003-09-05 23:19:14 +0000768 /* Set sensor number to zero */
769 pAC->I2c.MaxSens = 0;
770
771#ifndef SK_DIAG
772 /* Initialize Number of Dummy Reads */
773 pAC->I2c.DummyReads = SK_MAX_SENSORS;
774#endif
775
776 for (i = 0; i < SK_MAX_SENSORS; i++) {
777 pAC->I2c.SenTable[i].SenDesc = "unknown";
778 pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
779 pAC->I2c.SenTable[i].SenThreErrHigh = 0;
780 pAC->I2c.SenTable[i].SenThreErrLow = 0;
781 pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
782 pAC->I2c.SenTable[i].SenThreWarnLow = 0;
783 pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
784 pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
785 pAC->I2c.SenTable[i].SenValue = 0;
786 pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
787 pAC->I2c.SenTable[i].SenErrCts = 0;
788 pAC->I2c.SenTable[i].SenBegErrTS = 0;
789 pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
790 pAC->I2c.SenTable[i].SenRead = NULL;
791 pAC->I2c.SenTable[i].SenDev = 0;
792 }
793
794 /* Now we are "INIT data"ed */
795 pAC->I2c.InitLevel = SK_INIT_DATA;
796 return(0);
797} /* SkI2cInit0*/
798
799
800/*
801 * Do the init state 1 initialization
802 *
803 * initialize the following register of the LM80:
804 * Configuration register:
805 * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
806 *
807 * Interrupt Mask Register 1:
808 * - all interrupts are Disabled (0xff)
809 *
810 * Interrupt Mask Register 2:
811 * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
812 *
813 * Fan Divisor/RST_OUT register:
814 * - Divisors set to 1 (bits 00), all others 0s.
815 *
816 * OS# Configuration/Temperature resolution Register:
817 * - all 0s
818 *
819 */
820static int SkI2cInit1(
821SK_AC *pAC, /* Adapter Context */
822SK_IOC IoC) /* I/O Context */
823{
824 int i;
825 SK_U8 I2cSwCtrl;
826 SK_GEPORT *pPrt; /* GIni Port struct pointer */
827
828 if (pAC->I2c.InitLevel != SK_INIT_DATA) {
829 /* ReInit not needed in I2C module */
830 return(0);
831 }
832
833 /* Set the Direction of I2C-Data Pin to IN */
834 SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
835 /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
836 SK_I2C_GET_SW(IoC, &I2cSwCtrl);
837
838 if ((I2cSwCtrl & I2C_DATA) == 0) {
839 /* this is a 32-Bit board */
840 pAC->GIni.GIYukon32Bit = SK_TRUE;
wdenk9c53f402003-10-15 23:53:47 +0000841 return(0);
wdenkeb20ad32003-09-05 23:19:14 +0000842 }
843
844 /* Check for 64 Bit Yukon without sensors */
845 if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_CFG, 0) != 0) {
wdenk9c53f402003-10-15 23:53:47 +0000846 return(0);
wdenkeb20ad32003-09-05 23:19:14 +0000847 }
848
849 (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_1, 0);
wdenk9c53f402003-10-15 23:53:47 +0000850
wdenkeb20ad32003-09-05 23:19:14 +0000851 (void)SkI2cWrite(pAC, IoC, 0xff, LM80_ADDR, LM80_IMSK_2, 0);
wdenk9c53f402003-10-15 23:53:47 +0000852
wdenkeb20ad32003-09-05 23:19:14 +0000853 (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_FAN_CTRL, 0);
wdenk9c53f402003-10-15 23:53:47 +0000854
wdenkeb20ad32003-09-05 23:19:14 +0000855 (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, LM80_TEMP_CTRL, 0);
wdenk9c53f402003-10-15 23:53:47 +0000856
wdenkeb20ad32003-09-05 23:19:14 +0000857 (void)SkI2cWrite(pAC, IoC, LM80_CFG_START, LM80_ADDR, LM80_CFG, 0);
wdenk9c53f402003-10-15 23:53:47 +0000858
wdenkeb20ad32003-09-05 23:19:14 +0000859 /*
860 * MaxSens has to be updated here, because PhyType is not
861 * set when performing Init Level 0
862 */
863 pAC->I2c.MaxSens = 5;
wdenk9c53f402003-10-15 23:53:47 +0000864
wdenkeb20ad32003-09-05 23:19:14 +0000865 pPrt = &pAC->GIni.GP[0];
wdenk9c53f402003-10-15 23:53:47 +0000866
wdenkeb20ad32003-09-05 23:19:14 +0000867 if (pAC->GIni.GIGenesis) {
868 if (pPrt->PhyType == SK_PHY_BCOM) {
869 if (pAC->GIni.GIMacsFound == 1) {
870 pAC->I2c.MaxSens += 1;
871 }
872 else {
873 pAC->I2c.MaxSens += 3;
874 }
875 }
876 }
877 else {
878 pAC->I2c.MaxSens += 3;
879 }
wdenk9c53f402003-10-15 23:53:47 +0000880
wdenkeb20ad32003-09-05 23:19:14 +0000881 for (i = 0; i < pAC->I2c.MaxSens; i++) {
882 switch (i) {
883 case 0:
884 pAC->I2c.SenTable[i].SenDesc = "Temperature";
885 pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
886 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
887 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
888 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
889 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
890 pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
891 break;
892 case 1:
893 pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
894 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
895 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
896 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
897 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
898 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
899 pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
900 break;
901 case 2:
902 pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
903 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
904 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
905 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
906 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
907 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
908 pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
909 pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
910 break;
911 case 3:
912 pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
913 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
914 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
915 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
916 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
917 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
918 pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
919 break;
920 case 4:
921 if (pAC->GIni.GIGenesis) {
922 if (pPrt->PhyType == SK_PHY_BCOM) {
923 pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
924 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
925 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
926 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
927 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
928 }
929 else {
930 pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
931 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
932 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
933 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
934 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
935 }
936 }
937 else {
938 pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
939 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
940 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
941 if (pAC->GIni.GIVauxAvail) {
942 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
943 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
944 }
945 else {
946 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
947 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
948 }
949 }
950 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
951 pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
952 break;
953 case 5:
954 if (pAC->GIni.GIGenesis) {
955 pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
956 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
957 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
958 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
959 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
960 }
961 else {
962 pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC-Co 1V5";
963 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
964 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
965 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
966 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
967 }
968 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
969 pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
970 break;
971 case 6:
972 if (pAC->GIni.GIGenesis) {
973 pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
974 }
975 else {
976 pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
977 }
978 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
979 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
980 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
981 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
982 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
983 pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
984 break;
985 case 7:
986 if (pAC->GIni.GIGenesis) {
987 pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
988 pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
989 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
990 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
991 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
992 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
993 pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
994 }
995 else {
996 pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
997 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
998 pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
999 pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
1000 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
1001 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
1002 pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
1003 }
1004 break;
1005 default:
1006 SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
1007 SKERR_I2C_E001, SKERR_I2C_E001MSG);
1008 break;
1009 }
1010
1011 pAC->I2c.SenTable[i].SenValue = 0;
1012 pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
1013 pAC->I2c.SenTable[i].SenErrCts = 0;
1014 pAC->I2c.SenTable[i].SenBegErrTS = 0;
1015 pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
1016 pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
1017 pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
1018 }
1019
1020#ifndef SK_DIAG
1021 pAC->I2c.DummyReads = pAC->I2c.MaxSens;
1022#endif /* !SK_DIAG */
wdenk9c53f402003-10-15 23:53:47 +00001023
wdenkeb20ad32003-09-05 23:19:14 +00001024 /* Clear I2C IRQ */
1025 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
wdenk9c53f402003-10-15 23:53:47 +00001026
wdenkeb20ad32003-09-05 23:19:14 +00001027 /* Now we are I/O initialized */
1028 pAC->I2c.InitLevel = SK_INIT_IO;
1029 return(0);
1030} /* SkI2cInit1 */
1031
1032
1033/*
1034 * Init level 2: Start first sensor read.
1035 */
1036static int SkI2cInit2(
1037SK_AC *pAC, /* Adapter Context */
1038SK_IOC IoC) /* I/O Context */
1039{
1040 int ReadComplete;
1041 SK_SENSOR *pSen;
1042
1043 if (pAC->I2c.InitLevel != SK_INIT_IO) {
1044 /* ReInit not needed in I2C module */
1045 /* Init0 and Init2 not permitted */
1046 return(0);
1047 }
1048
1049 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
1050 ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
1051
1052 if (ReadComplete) {
1053 SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
1054 }
1055
1056 /* Now we are correctly initialized */
1057 pAC->I2c.InitLevel = SK_INIT_RUN;
1058
1059 return(0);
1060} /* SkI2cInit2*/
1061
1062
1063/*
1064 * Initialize I2C devices
1065 *
1066 * Get the first voltage value and discard it.
1067 * Go into temperature read mode. A default pointer is not set.
1068 *
1069 * The things to be done depend on the init level in the parameter list:
1070 * Level 0:
1071 * Initialize only the data structures. Do NOT access hardware.
1072 * Level 1:
1073 * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
1074 * Level 2:
1075 * Everything is possible. Interrupts may be used from now on.
1076 *
1077 * return:
1078 * 0 = success
1079 * other = error.
1080 */
1081int SkI2cInit(
1082SK_AC *pAC, /* Adapter Context */
1083SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */
1084int Level) /* Init Level */
1085{
1086
1087 switch (Level) {
1088 case SK_INIT_DATA:
1089 return(SkI2cInit0(pAC));
1090 case SK_INIT_IO:
1091 return(SkI2cInit1(pAC, IoC));
1092 case SK_INIT_RUN:
1093 return(SkI2cInit2(pAC, IoC));
1094 default:
1095 break;
1096 }
1097
1098 return(0);
1099} /* SkI2cInit */
1100
1101
1102#ifndef SK_DIAG
1103
1104/*
1105 * Interrupt service function for the I2C Interface
1106 *
1107 * Clears the Interrupt source
1108 *
1109 * Reads the register and check it for sending a trap.
1110 *
1111 * Starts the timer if necessary.
1112 */
1113void SkI2cIsr(
1114SK_AC *pAC, /* Adapter Context */
1115SK_IOC IoC) /* I/O Context */
1116{
1117 SK_EVPARA Para;
1118
1119 /* Clear I2C IRQ */
1120 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
1121
1122 Para.Para64 = 0;
1123 SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
1124} /* SkI2cIsr */
1125
1126
1127/*
1128 * Check this sensors Value against the threshold and send events.
1129 */
1130static void SkI2cCheckSensor(
1131SK_AC *pAC, /* Adapter Context */
1132SK_SENSOR *pSen)
1133{
1134 SK_EVPARA ParaLocal;
1135 SK_BOOL TooHigh; /* Is sensor too high? */
1136 SK_BOOL TooLow; /* Is sensor too low? */
1137 SK_U64 CurrTime; /* Current Time */
1138 SK_BOOL DoTrapSend; /* We need to send a trap */
1139 SK_BOOL DoErrLog; /* We need to log the error */
1140 SK_BOOL IsError; /* We need to log the error */
1141
1142 /* Check Dummy Reads first */
1143 if (pAC->I2c.DummyReads > 0) {
1144 pAC->I2c.DummyReads--;
1145 return;
1146 }
1147
1148 /* Get the current time */
1149 CurrTime = SkOsGetTime(pAC);
1150
1151 /* Set para to the most useful setting: The current sensor. */
1152 ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
1153
1154 /* Check the Value against the thresholds. First: Error Thresholds */
1155 TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
1156 TooLow = (pSen->SenValue < pSen->SenThreErrLow);
wdenk9c53f402003-10-15 23:53:47 +00001157
wdenkeb20ad32003-09-05 23:19:14 +00001158 IsError = SK_FALSE;
1159 if (TooHigh || TooLow) {
1160 /* Error condition is satisfied */
1161 DoTrapSend = SK_TRUE;
1162 DoErrLog = SK_TRUE;
1163
1164 /* Now error condition is satisfied */
1165 IsError = SK_TRUE;
1166
1167 if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
1168 /* This state is the former one */
1169
1170 /* So check first whether we have to send a trap */
1171 if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
1172 CurrTime) {
1173 /*
1174 * Do NOT send the Trap. The hold back time
1175 * has to run out first.
1176 */
1177 DoTrapSend = SK_FALSE;
1178 }
1179
1180 /* Check now whether we have to log an Error */
1181 if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
1182 CurrTime) {
1183 /*
1184 * Do NOT log the error. The hold back time
1185 * has to run out first.
1186 */
1187 DoErrLog = SK_FALSE;
1188 }
1189 }
1190 else {
1191 /* We came from a different state -> Set Begin Time Stamp */
1192 pSen->SenBegErrTS = CurrTime;
1193 pSen->SenErrFlag = SK_SEN_ERR_ERR;
1194 }
1195
1196 if (DoTrapSend) {
1197 /* Set current Time */
1198 pSen->SenLastErrTrapTS = CurrTime;
1199 pSen->SenErrCts++;
1200
1201 /* Queue PNMI Event */
1202 SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
1203 SK_PNMI_EVT_SEN_ERR_UPP :
1204 SK_PNMI_EVT_SEN_ERR_LOW),
1205 ParaLocal);
1206 }
1207
1208 if (DoErrLog) {
1209 /* Set current Time */
1210 pSen->SenLastErrLogTS = CurrTime;
1211
1212 if (pSen->SenType == SK_SEN_TEMP) {
1213 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011,
1214 SKERR_I2C_E011MSG);
1215 } else if (pSen->SenType == SK_SEN_VOLT) {
1216 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012,
1217 SKERR_I2C_E012MSG);
1218 } else
1219 {
1220 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015,
1221 SKERR_I2C_E015MSG);
1222 }
1223 }
1224 }
1225
1226 /* Check the Value against the thresholds */
1227 /* 2nd: Warning thresholds */
1228 TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
1229 TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
wdenk9c53f402003-10-15 23:53:47 +00001230
wdenkeb20ad32003-09-05 23:19:14 +00001231 if (!IsError && (TooHigh || TooLow)) {
1232 /* Error condition is satisfied */
1233 DoTrapSend = SK_TRUE;
1234 DoErrLog = SK_TRUE;
1235
1236 if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
1237 /* This state is the former one */
1238
1239 /* So check first whether we have to send a trap */
1240 if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD >
1241 CurrTime) {
1242 /*
1243 * Do NOT send the Trap. The hold back time
1244 * has to run out first.
1245 */
1246 DoTrapSend = SK_FALSE;
1247 }
1248
1249 /* Check now whether we have to log an Error */
1250 if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD >
1251 CurrTime) {
1252 /*
1253 * Do NOT log the error. The hold back time
1254 * has to run out first.
1255 */
1256 DoErrLog = SK_FALSE;
1257 }
1258 }
1259 else {
1260 /* We came from a different state -> Set Begin Time Stamp */
1261 pSen->SenBegWarnTS = CurrTime;
1262 pSen->SenErrFlag = SK_SEN_ERR_WARN;
1263 }
1264
1265 if (DoTrapSend) {
1266 /* Set current Time */
1267 pSen->SenLastWarnTrapTS = CurrTime;
1268 pSen->SenWarnCts++;
1269
1270 /* Queue PNMI Event */
1271 SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
1272 SK_PNMI_EVT_SEN_WAR_UPP :
1273 SK_PNMI_EVT_SEN_WAR_LOW),
1274 ParaLocal);
1275 }
1276
1277 if (DoErrLog) {
1278 /* Set current Time */
1279 pSen->SenLastWarnLogTS = CurrTime;
1280
1281 if (pSen->SenType == SK_SEN_TEMP) {
1282 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009,
1283 SKERR_I2C_E009MSG);
1284 } else if (pSen->SenType == SK_SEN_VOLT) {
1285 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010,
1286 SKERR_I2C_E010MSG);
1287 } else
1288 {
1289 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014,
1290 SKERR_I2C_E014MSG);
1291 }
1292 }
1293 }
1294
1295 /* Check for NO error at all */
1296 if (!IsError && !TooHigh && !TooLow) {
1297 /* Set o.k. Status if no error and no warning condition */
1298 pSen->SenErrFlag = SK_SEN_ERR_OK;
1299 }
1300
1301 /* End of check against the thresholds */
1302
1303 /* Bug fix AF: 16.Aug.2001: Correct the init base
1304 * of LM80 sensor.
1305 */
1306 if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
1307
wdenk9c53f402003-10-15 23:53:47 +00001308 pSen->SenInit = SK_SEN_DYN_INIT_NONE;
wdenkeb20ad32003-09-05 23:19:14 +00001309
1310 if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
1311 /* 5V PCI-IO Voltage */
1312 pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
1313 pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
1314 }
1315 else {
1316 /* 3.3V PCI-IO Voltage */
1317 pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
1318 pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
1319 }
1320 }
wdenk9c53f402003-10-15 23:53:47 +00001321
wdenkeb20ad32003-09-05 23:19:14 +00001322#if 0
1323 /* Dynamic thresholds also for VAUX of LM80 sensor */
1324 if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
1325
wdenk9c53f402003-10-15 23:53:47 +00001326 pSen->SenInit = SK_SEN_DYN_INIT_NONE;
wdenkeb20ad32003-09-05 23:19:14 +00001327
1328 /* 3.3V VAUX Voltage */
1329 if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
1330 pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
1331 pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
1332 }
1333 /* 0V VAUX Voltage */
1334 else {
1335 pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
1336 pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
1337 }
1338 }
1339
1340 /*
1341 * Check initialization state:
1342 * The VIO Thresholds need adaption
1343 */
1344 if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
1345 pSen->SenValue > SK_SEN_WARNLOW2C &&
1346 pSen->SenValue < SK_SEN_WARNHIGH2) {
1347 pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
1348 pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
1349 pSen->SenInit = SK_TRUE;
1350 }
1351
1352 if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
1353 pSen->SenValue > SK_SEN_WARNLOW2 &&
1354 pSen->SenValue < SK_SEN_WARNHIGH2C) {
1355 pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
1356 pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
1357 pSen->SenInit = SK_TRUE;
1358 }
1359#endif
1360
1361 if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
1362 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
1363 }
1364} /* SkI2cCheckSensor*/
1365
1366
1367/*
1368 * The only Event to be served is the timeout event
1369 *
1370 */
1371int SkI2cEvent(
1372SK_AC *pAC, /* Adapter Context */
1373SK_IOC IoC, /* I/O Context */
1374SK_U32 Event, /* Module specific Event */
1375SK_EVPARA Para) /* Event specific Parameter */
1376{
1377 int ReadComplete;
1378 SK_SENSOR *pSen;
1379 SK_U32 Time;
1380 SK_EVPARA ParaLocal;
1381 int i;
1382
1383 /* New case: no sensors */
1384 if (pAC->I2c.MaxSens == 0) {
1385 return(0);
1386 }
1387
1388 switch (Event) {
1389 case SK_I2CEV_IRQ:
1390 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
1391 ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
1392
1393 if (ReadComplete) {
1394 /* Check sensor against defined thresholds */
1395 SkI2cCheckSensor (pAC, pSen);
1396
1397 /* Increment Current sensor and set appropriate Timeout */
1398 pAC->I2c.CurrSens++;
1399 if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
1400 pAC->I2c.CurrSens = 0;
1401 Time = SK_I2C_TIM_LONG;
1402 }
1403 else {
1404 Time = SK_I2C_TIM_SHORT;
1405 }
1406
1407 /* Start Timer */
1408 ParaLocal.Para64 = (SK_U64)0;
1409
1410 pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
wdenk9c53f402003-10-15 23:53:47 +00001411
wdenkeb20ad32003-09-05 23:19:14 +00001412 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
1413 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
1414 }
wdenk9c53f402003-10-15 23:53:47 +00001415 else {
wdenkeb20ad32003-09-05 23:19:14 +00001416 /* Start Timer */
1417 ParaLocal.Para64 = (SK_U64)0;
1418
1419 pAC->I2c.TimerMode = SK_TIMER_WATCH_STATEMACHINE;
1420
wdenk9c53f402003-10-15 23:53:47 +00001421 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
wdenkeb20ad32003-09-05 23:19:14 +00001422 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
1423 }
1424 break;
1425 case SK_I2CEV_TIM:
1426 if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
1427
1428 ParaLocal.Para64 = (SK_U64)0;
1429 SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
1430
1431 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
1432 ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
1433
1434 if (ReadComplete) {
1435 /* Check sensor against defined thresholds */
1436 SkI2cCheckSensor (pAC, pSen);
1437
1438 /* Increment Current sensor and set appropriate Timeout */
1439 pAC->I2c.CurrSens++;
1440 if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
1441 pAC->I2c.CurrSens = 0;
1442 Time = SK_I2C_TIM_LONG;
1443 }
1444 else {
1445 Time = SK_I2C_TIM_SHORT;
1446 }
1447
1448 /* Start Timer */
1449 ParaLocal.Para64 = (SK_U64)0;
1450
1451 pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
1452
1453 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
1454 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
1455 }
1456 }
1457 else {
1458 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
1459 pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
1460 SK_I2C_STOP(IoC);
1461
1462 /* Increment Current sensor and set appropriate Timeout */
1463 pAC->I2c.CurrSens++;
1464 if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
1465 pAC->I2c.CurrSens = 0;
1466 Time = SK_I2C_TIM_LONG;
1467 }
1468 else {
1469 Time = SK_I2C_TIM_SHORT;
1470 }
1471
1472 /* Start Timer */
1473 ParaLocal.Para64 = (SK_U64)0;
1474
1475 pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
1476
1477 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
1478 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
1479 }
1480 break;
1481 case SK_I2CEV_CLEAR:
1482 for (i = 0; i < SK_MAX_SENSORS; i++) {
1483 pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
1484 pAC->I2c.SenTable[i].SenErrCts = 0;
1485 pAC->I2c.SenTable[i].SenWarnCts = 0;
1486 pAC->I2c.SenTable[i].SenBegErrTS = 0;
1487 pAC->I2c.SenTable[i].SenBegWarnTS = 0;
1488 pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
1489 pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
1490 pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
1491 pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
1492 }
1493 break;
1494 default:
1495 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
1496 }
1497
1498 return(0);
1499} /* SkI2cEvent*/
1500
1501#endif /* !SK_DIAG */