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