diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/sk98lin/ski2c.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/sk98lin/ski2c.c')
-rw-r--r-- | drivers/net/sk98lin/ski2c.c | 1296 |
1 files changed, 1296 insertions, 0 deletions
diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c new file mode 100644 index 000000000000..075a0464e56b --- /dev/null +++ b/drivers/net/sk98lin/ski2c.c | |||
@@ -0,0 +1,1296 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Name: ski2c.c | ||
4 | * Project: Gigabit Ethernet Adapters, TWSI-Module | ||
5 | * Version: $Revision: 1.59 $ | ||
6 | * Date: $Date: 2003/10/20 09:07:25 $ | ||
7 | * Purpose: Functions to access Voltage and Temperature Sensor | ||
8 | * | ||
9 | ******************************************************************************/ | ||
10 | |||
11 | /****************************************************************************** | ||
12 | * | ||
13 | * (C)Copyright 1998-2002 SysKonnect. | ||
14 | * (C)Copyright 2002-2003 Marvell. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * The information in this file is provided "AS IS" without warranty. | ||
22 | * | ||
23 | ******************************************************************************/ | ||
24 | |||
25 | /* | ||
26 | * I2C Protocol | ||
27 | */ | ||
28 | #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) | ||
29 | static const char SysKonnectFileId[] = | ||
30 | "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. "; | ||
31 | #endif | ||
32 | |||
33 | #include "h/skdrv1st.h" /* Driver Specific Definitions */ | ||
34 | #include "h/lm80.h" | ||
35 | #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ | ||
36 | |||
37 | #ifdef __C2MAN__ | ||
38 | /* | ||
39 | I2C protocol implementation. | ||
40 | |||
41 | General Description: | ||
42 | |||
43 | The I2C protocol is used for the temperature sensors and for | ||
44 | the serial EEPROM which hold the configuration. | ||
45 | |||
46 | This file covers functions that allow to read write and do | ||
47 | some bulk requests a specified I2C address. | ||
48 | |||
49 | The Genesis has 2 I2C buses. One for the EEPROM which holds | ||
50 | the VPD Data and one for temperature and voltage sensor. | ||
51 | The following picture shows the I2C buses, I2C devices and | ||
52 | their control registers. | ||
53 | |||
54 | Note: The VPD functions are in skvpd.c | ||
55 | . | ||
56 | . PCI Config I2C Bus for VPD Data: | ||
57 | . | ||
58 | . +------------+ | ||
59 | . | VPD EEPROM | | ||
60 | . +------------+ | ||
61 | . | | ||
62 | . | <-- I2C | ||
63 | . | | ||
64 | . +-----------+-----------+ | ||
65 | . | | | ||
66 | . +-----------------+ +-----------------+ | ||
67 | . | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG | | ||
68 | . +-----------------+ +-----------------+ | ||
69 | . | ||
70 | . | ||
71 | . I2C Bus for LM80 sensor: | ||
72 | . | ||
73 | . +-----------------+ | ||
74 | . | Temperature and | | ||
75 | . | Voltage Sensor | | ||
76 | . | LM80 | | ||
77 | . +-----------------+ | ||
78 | . | | ||
79 | . | | ||
80 | . I2C --> | | ||
81 | . | | ||
82 | . +----+ | ||
83 | . +-------------->| OR |<--+ | ||
84 | . | +----+ | | ||
85 | . +------+------+ | | ||
86 | . | | | | ||
87 | . +--------+ +--------+ +----------+ | ||
88 | . | B2_I2C | | B2_I2C | | B2_I2C | | ||
89 | . | _CTRL | | _DATA | | _SW | | ||
90 | . +--------+ +--------+ +----------+ | ||
91 | . | ||
92 | The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL | ||
93 | and B2_I2C_DATA registers. | ||
94 | For driver software it is recommended to use the I2C control and | ||
95 | data register, because I2C bus timing is done by the ASIC and | ||
96 | an interrupt may be received when the I2C request is completed. | ||
97 | |||
98 | Clock Rate Timing: MIN MAX generated by | ||
99 | VPD EEPROM: 50 kHz 100 kHz HW | ||
100 | LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW | ||
101 | LM80 over B2_I2C_SW register 0 400 kHz SW | ||
102 | |||
103 | Note: The clock generated by the hardware is dependend on the | ||
104 | PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD | ||
105 | clock is 50 kHz. | ||
106 | */ | ||
107 | intro() | ||
108 | {} | ||
109 | #endif | ||
110 | |||
111 | #ifdef SK_DIAG | ||
112 | /* | ||
113 | * I2C Fast Mode timing values used by the LM80. | ||
114 | * If new devices are added to the I2C bus the timing values have to be checked. | ||
115 | */ | ||
116 | #ifndef I2C_SLOW_TIMING | ||
117 | #define T_CLK_LOW 1300L /* clock low time in ns */ | ||
118 | #define T_CLK_HIGH 600L /* clock high time in ns */ | ||
119 | #define T_DATA_IN_SETUP 100L /* data in Set-up Time */ | ||
120 | #define T_START_HOLD 600L /* start condition hold time */ | ||
121 | #define T_START_SETUP 600L /* start condition Set-up time */ | ||
122 | #define T_STOP_SETUP 600L /* stop condition Set-up time */ | ||
123 | #define T_BUS_IDLE 1300L /* time the bus must free after Tx */ | ||
124 | #define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */ | ||
125 | #else /* I2C_SLOW_TIMING */ | ||
126 | /* I2C Standard Mode Timing */ | ||
127 | #define T_CLK_LOW 4700L /* clock low time in ns */ | ||
128 | #define T_CLK_HIGH 4000L /* clock high time in ns */ | ||
129 | #define T_DATA_IN_SETUP 250L /* data in Set-up Time */ | ||
130 | #define T_START_HOLD 4000L /* start condition hold time */ | ||
131 | #define T_START_SETUP 4700L /* start condition Set-up time */ | ||
132 | #define T_STOP_SETUP 4000L /* stop condition Set-up time */ | ||
133 | #define T_BUS_IDLE 4700L /* time the bus must free after Tx */ | ||
134 | #endif /* !I2C_SLOW_TIMING */ | ||
135 | |||
136 | #define NS2BCLK(x) (((x)*125)/10000) | ||
137 | |||
138 | /* | ||
139 | * I2C Wire Operations | ||
140 | * | ||
141 | * About I2C_CLK_LOW(): | ||
142 | * | ||
143 | * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting | ||
144 | * clock to low, to prevent the ASIC and the I2C data client from driving the | ||
145 | * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client | ||
146 | * send an 'ACK'). See also Concentrator Bugreport No. 10192. | ||
147 | */ | ||
148 | #define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA) | ||
149 | #define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA) | ||
150 | #define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR) | ||
151 | #define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA) | ||
152 | #define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK) | ||
153 | #define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR) | ||
154 | #define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK) | ||
155 | |||
156 | #define NS2CLKT(x) ((x*125L)/10000) | ||
157 | |||
158 | /*--------------- I2C Interface Register Functions --------------- */ | ||
159 | |||
160 | /* | ||
161 | * sending one bit | ||
162 | */ | ||
163 | void SkI2cSndBit( | ||
164 | SK_IOC IoC, /* I/O Context */ | ||
165 | SK_U8 Bit) /* Bit to send */ | ||
166 | { | ||
167 | I2C_DATA_OUT(IoC); | ||
168 | if (Bit) { | ||
169 | I2C_DATA_HIGH(IoC); | ||
170 | } | ||
171 | else { | ||
172 | I2C_DATA_LOW(IoC); | ||
173 | } | ||
174 | SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP)); | ||
175 | I2C_CLK_HIGH(IoC); | ||
176 | SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); | ||
177 | I2C_CLK_LOW(IoC); | ||
178 | } /* SkI2cSndBit*/ | ||
179 | |||
180 | |||
181 | /* | ||
182 | * Signal a start to the I2C Bus. | ||
183 | * | ||
184 | * A start is signaled when data goes to low in a high clock cycle. | ||
185 | * | ||
186 | * Ends with Clock Low. | ||
187 | * | ||
188 | * Status: not tested | ||
189 | */ | ||
190 | void SkI2cStart( | ||
191 | SK_IOC IoC) /* I/O Context */ | ||
192 | { | ||
193 | /* Init data and Clock to output lines */ | ||
194 | /* Set Data high */ | ||
195 | I2C_DATA_OUT(IoC); | ||
196 | I2C_DATA_HIGH(IoC); | ||
197 | /* Set Clock high */ | ||
198 | I2C_CLK_HIGH(IoC); | ||
199 | |||
200 | SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP)); | ||
201 | |||
202 | /* Set Data Low */ | ||
203 | I2C_DATA_LOW(IoC); | ||
204 | |||
205 | SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD)); | ||
206 | |||
207 | /* Clock low without Data to Input */ | ||
208 | I2C_START_COND(IoC); | ||
209 | |||
210 | SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW)); | ||
211 | } /* SkI2cStart */ | ||
212 | |||
213 | |||
214 | void SkI2cStop( | ||
215 | SK_IOC IoC) /* I/O Context */ | ||
216 | { | ||
217 | /* Init data and Clock to output lines */ | ||
218 | /* Set Data low */ | ||
219 | I2C_DATA_OUT(IoC); | ||
220 | I2C_DATA_LOW(IoC); | ||
221 | |||
222 | SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); | ||
223 | |||
224 | /* Set Clock high */ | ||
225 | I2C_CLK_HIGH(IoC); | ||
226 | |||
227 | SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP)); | ||
228 | |||
229 | /* | ||
230 | * Set Data High: Do it by setting the Data Line to Input. | ||
231 | * Because of a pull up resistor the Data Line | ||
232 | * floods to high. | ||
233 | */ | ||
234 | I2C_DATA_IN(IoC); | ||
235 | |||
236 | /* | ||
237 | * When I2C activity is stopped | ||
238 | * o DATA should be set to input and | ||
239 | * o CLOCK should be set to high! | ||
240 | */ | ||
241 | SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE)); | ||
242 | } /* SkI2cStop */ | ||
243 | |||
244 | |||
245 | /* | ||
246 | * Receive just one bit via the I2C bus. | ||
247 | * | ||
248 | * Note: Clock must be set to LOW before calling this function. | ||
249 | * | ||
250 | * Returns The received bit. | ||
251 | */ | ||
252 | int SkI2cRcvBit( | ||
253 | SK_IOC IoC) /* I/O Context */ | ||
254 | { | ||
255 | int Bit; | ||
256 | SK_U8 I2cSwCtrl; | ||
257 | |||
258 | /* Init data as input line */ | ||
259 | I2C_DATA_IN(IoC); | ||
260 | |||
261 | SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); | ||
262 | |||
263 | I2C_CLK_HIGH(IoC); | ||
264 | |||
265 | SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); | ||
266 | |||
267 | SK_I2C_GET_SW(IoC, &I2cSwCtrl); | ||
268 | |||
269 | Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0; | ||
270 | |||
271 | I2C_CLK_LOW(IoC); | ||
272 | SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT)); | ||
273 | |||
274 | return(Bit); | ||
275 | } /* SkI2cRcvBit */ | ||
276 | |||
277 | |||
278 | /* | ||
279 | * Receive an ACK. | ||
280 | * | ||
281 | * returns 0 If acknowledged | ||
282 | * 1 in case of an error | ||
283 | */ | ||
284 | int SkI2cRcvAck( | ||
285 | SK_IOC IoC) /* I/O Context */ | ||
286 | { | ||
287 | /* | ||
288 | * Received bit must be zero. | ||
289 | */ | ||
290 | return(SkI2cRcvBit(IoC) != 0); | ||
291 | } /* SkI2cRcvAck */ | ||
292 | |||
293 | |||
294 | /* | ||
295 | * Send an NACK. | ||
296 | */ | ||
297 | void SkI2cSndNAck( | ||
298 | SK_IOC IoC) /* I/O Context */ | ||
299 | { | ||
300 | /* | ||
301 | * Received bit must be zero. | ||
302 | */ | ||
303 | SkI2cSndBit(IoC, 1); | ||
304 | } /* SkI2cSndNAck */ | ||
305 | |||
306 | |||
307 | /* | ||
308 | * Send an ACK. | ||
309 | */ | ||
310 | void SkI2cSndAck( | ||
311 | SK_IOC IoC) /* I/O Context */ | ||
312 | { | ||
313 | /* | ||
314 | * Received bit must be zero. | ||
315 | */ | ||
316 | SkI2cSndBit(IoC, 0); | ||
317 | } /* SkI2cSndAck */ | ||
318 | |||
319 | |||
320 | /* | ||
321 | * Send one byte to the I2C device and wait for ACK. | ||
322 | * | ||
323 | * Return acknowleged status. | ||
324 | */ | ||
325 | int SkI2cSndByte( | ||
326 | SK_IOC IoC, /* I/O Context */ | ||
327 | int Byte) /* byte to send */ | ||
328 | { | ||
329 | int i; | ||
330 | |||
331 | for (i = 0; i < 8; i++) { | ||
332 | if (Byte & (1<<(7-i))) { | ||
333 | SkI2cSndBit(IoC, 1); | ||
334 | } | ||
335 | else { | ||
336 | SkI2cSndBit(IoC, 0); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | return(SkI2cRcvAck(IoC)); | ||
341 | } /* SkI2cSndByte */ | ||
342 | |||
343 | |||
344 | /* | ||
345 | * Receive one byte and ack it. | ||
346 | * | ||
347 | * Return byte. | ||
348 | */ | ||
349 | int SkI2cRcvByte( | ||
350 | SK_IOC IoC, /* I/O Context */ | ||
351 | int Last) /* Last Byte Flag */ | ||
352 | { | ||
353 | int i; | ||
354 | int Byte = 0; | ||
355 | |||
356 | for (i = 0; i < 8; i++) { | ||
357 | Byte <<= 1; | ||
358 | Byte |= SkI2cRcvBit(IoC); | ||
359 | } | ||
360 | |||
361 | if (Last) { | ||
362 | SkI2cSndNAck(IoC); | ||
363 | } | ||
364 | else { | ||
365 | SkI2cSndAck(IoC); | ||
366 | } | ||
367 | |||
368 | return(Byte); | ||
369 | } /* SkI2cRcvByte */ | ||
370 | |||
371 | |||
372 | /* | ||
373 | * Start dialog and send device address | ||
374 | * | ||
375 | * Return 0 if acknowleged, 1 in case of an error | ||
376 | */ | ||
377 | int SkI2cSndDev( | ||
378 | SK_IOC IoC, /* I/O Context */ | ||
379 | int Addr, /* Device Address */ | ||
380 | int Rw) /* Read / Write Flag */ | ||
381 | { | ||
382 | SkI2cStart(IoC); | ||
383 | Rw = ~Rw; | ||
384 | Rw &= I2C_WRITE; | ||
385 | return(SkI2cSndByte(IoC, (Addr<<1) | Rw)); | ||
386 | } /* SkI2cSndDev */ | ||
387 | |||
388 | #endif /* SK_DIAG */ | ||
389 | |||
390 | /*----------------- I2C CTRL Register Functions ----------*/ | ||
391 | |||
392 | /* | ||
393 | * waits for a completion of an I2C transfer | ||
394 | * | ||
395 | * returns 0: success, transfer completes | ||
396 | * 1: error, transfer does not complete, I2C transfer | ||
397 | * killed, wait loop terminated. | ||
398 | */ | ||
399 | int SkI2cWait( | ||
400 | SK_AC *pAC, /* Adapter Context */ | ||
401 | SK_IOC IoC, /* I/O Context */ | ||
402 | int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */ | ||
403 | { | ||
404 | SK_U64 StartTime; | ||
405 | SK_U64 CurrentTime; | ||
406 | SK_U32 I2cCtrl; | ||
407 | |||
408 | StartTime = SkOsGetTime(pAC); | ||
409 | |||
410 | do { | ||
411 | CurrentTime = SkOsGetTime(pAC); | ||
412 | |||
413 | if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) { | ||
414 | |||
415 | SK_I2C_STOP(IoC); | ||
416 | #ifndef SK_DIAG | ||
417 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG); | ||
418 | #endif /* !SK_DIAG */ | ||
419 | return(1); | ||
420 | } | ||
421 | |||
422 | SK_I2C_GET_CTL(IoC, &I2cCtrl); | ||
423 | |||
424 | #ifdef xYUKON_DBG | ||
425 | printf("StartTime=%lu, CurrentTime=%lu\n", | ||
426 | StartTime, CurrentTime); | ||
427 | if (kbhit()) { | ||
428 | return(1); | ||
429 | } | ||
430 | #endif /* YUKON_DBG */ | ||
431 | |||
432 | } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31); | ||
433 | |||
434 | return(0); | ||
435 | } /* SkI2cWait */ | ||
436 | |||
437 | |||
438 | /* | ||
439 | * waits for a completion of an I2C transfer | ||
440 | * | ||
441 | * Returns | ||
442 | * Nothing | ||
443 | */ | ||
444 | void SkI2cWaitIrq( | ||
445 | SK_AC *pAC, /* Adapter Context */ | ||
446 | SK_IOC IoC) /* I/O Context */ | ||
447 | { | ||
448 | SK_SENSOR *pSen; | ||
449 | SK_U64 StartTime; | ||
450 | SK_U32 IrqSrc; | ||
451 | |||
452 | pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; | ||
453 | |||
454 | if (pSen->SenState == SK_SEN_IDLE) { | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | StartTime = SkOsGetTime(pAC); | ||
459 | |||
460 | do { | ||
461 | if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) { | ||
462 | |||
463 | SK_I2C_STOP(IoC); | ||
464 | #ifndef SK_DIAG | ||
465 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG); | ||
466 | #endif /* !SK_DIAG */ | ||
467 | return; | ||
468 | } | ||
469 | |||
470 | SK_IN32(IoC, B0_ISRC, &IrqSrc); | ||
471 | |||
472 | } while ((IrqSrc & IS_I2C_READY) == 0); | ||
473 | |||
474 | pSen->SenState = SK_SEN_IDLE; | ||
475 | return; | ||
476 | } /* SkI2cWaitIrq */ | ||
477 | |||
478 | /* | ||
479 | * writes a single byte or 4 bytes into the I2C device | ||
480 | * | ||
481 | * returns 0: success | ||
482 | * 1: error | ||
483 | */ | ||
484 | int SkI2cWrite( | ||
485 | SK_AC *pAC, /* Adapter Context */ | ||
486 | SK_IOC IoC, /* I/O Context */ | ||
487 | SK_U32 I2cData, /* I2C Data to write */ | ||
488 | int I2cDev, /* I2C Device Address */ | ||
489 | int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ | ||
490 | int I2cReg, /* I2C Device Register Address */ | ||
491 | int I2cBurst) /* I2C Burst Flag */ | ||
492 | { | ||
493 | SK_OUT32(IoC, B2_I2C_DATA, I2cData); | ||
494 | |||
495 | SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst); | ||
496 | |||
497 | return(SkI2cWait(pAC, IoC, I2C_WRITE)); | ||
498 | } /* SkI2cWrite*/ | ||
499 | |||
500 | |||
501 | #ifdef SK_DIAG | ||
502 | /* | ||
503 | * reads a single byte or 4 bytes from the I2C device | ||
504 | * | ||
505 | * returns the word read | ||
506 | */ | ||
507 | SK_U32 SkI2cRead( | ||
508 | SK_AC *pAC, /* Adapter Context */ | ||
509 | SK_IOC IoC, /* I/O Context */ | ||
510 | int I2cDev, /* I2C Device Address */ | ||
511 | int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ | ||
512 | int I2cReg, /* I2C Device Register Address */ | ||
513 | int I2cBurst) /* I2C Burst Flag */ | ||
514 | { | ||
515 | SK_U32 Data; | ||
516 | |||
517 | SK_OUT32(IoC, B2_I2C_DATA, 0); | ||
518 | SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst); | ||
519 | |||
520 | if (SkI2cWait(pAC, IoC, I2C_READ) != 0) { | ||
521 | w_print("%s\n", SKERR_I2C_E002MSG); | ||
522 | } | ||
523 | |||
524 | SK_IN32(IoC, B2_I2C_DATA, &Data); | ||
525 | |||
526 | return(Data); | ||
527 | } /* SkI2cRead */ | ||
528 | #endif /* SK_DIAG */ | ||
529 | |||
530 | |||
531 | /* | ||
532 | * read a sensor's value | ||
533 | * | ||
534 | * This function reads a sensor's value from the I2C sensor chip. The sensor | ||
535 | * is defined by its index into the sensors database in the struct pAC points | ||
536 | * to. | ||
537 | * Returns | ||
538 | * 1 if the read is completed | ||
539 | * 0 if the read must be continued (I2C Bus still allocated) | ||
540 | */ | ||
541 | int SkI2cReadSensor( | ||
542 | SK_AC *pAC, /* Adapter Context */ | ||
543 | SK_IOC IoC, /* I/O Context */ | ||
544 | SK_SENSOR *pSen) /* Sensor to be read */ | ||
545 | { | ||
546 | if (pSen->SenRead != NULL) { | ||
547 | return((*pSen->SenRead)(pAC, IoC, pSen)); | ||
548 | } | ||
549 | else { | ||
550 | return(0); /* no success */ | ||
551 | } | ||
552 | } /* SkI2cReadSensor */ | ||
553 | |||
554 | /* | ||
555 | * Do the Init state 0 initialization | ||
556 | */ | ||
557 | static int SkI2cInit0( | ||
558 | SK_AC *pAC) /* Adapter Context */ | ||
559 | { | ||
560 | int i; | ||
561 | |||
562 | /* Begin with first sensor */ | ||
563 | pAC->I2c.CurrSens = 0; | ||
564 | |||
565 | /* Begin with timeout control for state machine */ | ||
566 | pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; | ||
567 | |||
568 | /* Set sensor number to zero */ | ||
569 | pAC->I2c.MaxSens = 0; | ||
570 | |||
571 | #ifndef SK_DIAG | ||
572 | /* Initialize Number of Dummy Reads */ | ||
573 | pAC->I2c.DummyReads = SK_MAX_SENSORS; | ||
574 | #endif | ||
575 | |||
576 | for (i = 0; i < SK_MAX_SENSORS; i++) { | ||
577 | pAC->I2c.SenTable[i].SenDesc = "unknown"; | ||
578 | pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN; | ||
579 | pAC->I2c.SenTable[i].SenThreErrHigh = 0; | ||
580 | pAC->I2c.SenTable[i].SenThreErrLow = 0; | ||
581 | pAC->I2c.SenTable[i].SenThreWarnHigh = 0; | ||
582 | pAC->I2c.SenTable[i].SenThreWarnLow = 0; | ||
583 | pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; | ||
584 | pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE; | ||
585 | pAC->I2c.SenTable[i].SenValue = 0; | ||
586 | pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT; | ||
587 | pAC->I2c.SenTable[i].SenErrCts = 0; | ||
588 | pAC->I2c.SenTable[i].SenBegErrTS = 0; | ||
589 | pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; | ||
590 | pAC->I2c.SenTable[i].SenRead = NULL; | ||
591 | pAC->I2c.SenTable[i].SenDev = 0; | ||
592 | } | ||
593 | |||
594 | /* Now we are "INIT data"ed */ | ||
595 | pAC->I2c.InitLevel = SK_INIT_DATA; | ||
596 | return(0); | ||
597 | } /* SkI2cInit0*/ | ||
598 | |||
599 | |||
600 | /* | ||
601 | * Do the init state 1 initialization | ||
602 | * | ||
603 | * initialize the following register of the LM80: | ||
604 | * Configuration register: | ||
605 | * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT | ||
606 | * | ||
607 | * Interrupt Mask Register 1: | ||
608 | * - all interrupts are Disabled (0xff) | ||
609 | * | ||
610 | * Interrupt Mask Register 2: | ||
611 | * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter. | ||
612 | * | ||
613 | * Fan Divisor/RST_OUT register: | ||
614 | * - Divisors set to 1 (bits 00), all others 0s. | ||
615 | * | ||
616 | * OS# Configuration/Temperature resolution Register: | ||
617 | * - all 0s | ||
618 | * | ||
619 | */ | ||
620 | static int SkI2cInit1( | ||
621 | SK_AC *pAC, /* Adapter Context */ | ||
622 | SK_IOC IoC) /* I/O Context */ | ||
623 | { | ||
624 | int i; | ||
625 | SK_U8 I2cSwCtrl; | ||
626 | SK_GEPORT *pPrt; /* GIni Port struct pointer */ | ||
627 | |||
628 | if (pAC->I2c.InitLevel != SK_INIT_DATA) { | ||
629 | /* ReInit not needed in I2C module */ | ||
630 | return(0); | ||
631 | } | ||
632 | |||
633 | /* Set the Direction of I2C-Data Pin to IN */ | ||
634 | SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA); | ||
635 | /* Check for 32-Bit Yukon with Low at I2C-Data Pin */ | ||
636 | SK_I2C_GET_SW(IoC, &I2cSwCtrl); | ||
637 | |||
638 | if ((I2cSwCtrl & I2C_DATA) == 0) { | ||
639 | /* this is a 32-Bit board */ | ||
640 | pAC->GIni.GIYukon32Bit = SK_TRUE; | ||
641 | return(0); | ||
642 | } | ||
643 | |||
644 | /* Check for 64 Bit Yukon without sensors */ | ||
645 | if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) { | ||
646 | return(0); | ||
647 | } | ||
648 | |||
649 | (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0); | ||
650 | |||
651 | (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0); | ||
652 | |||
653 | (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0); | ||
654 | |||
655 | (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0); | ||
656 | |||
657 | (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV, | ||
658 | LM80_CFG, 0); | ||
659 | |||
660 | /* | ||
661 | * MaxSens has to be updated here, because PhyType is not | ||
662 | * set when performing Init Level 0 | ||
663 | */ | ||
664 | pAC->I2c.MaxSens = 5; | ||
665 | |||
666 | pPrt = &pAC->GIni.GP[0]; | ||
667 | |||
668 | if (pAC->GIni.GIGenesis) { | ||
669 | if (pPrt->PhyType == SK_PHY_BCOM) { | ||
670 | if (pAC->GIni.GIMacsFound == 1) { | ||
671 | pAC->I2c.MaxSens += 1; | ||
672 | } | ||
673 | else { | ||
674 | pAC->I2c.MaxSens += 3; | ||
675 | } | ||
676 | } | ||
677 | } | ||
678 | else { | ||
679 | pAC->I2c.MaxSens += 3; | ||
680 | } | ||
681 | |||
682 | for (i = 0; i < pAC->I2c.MaxSens; i++) { | ||
683 | switch (i) { | ||
684 | case 0: | ||
685 | pAC->I2c.SenTable[i].SenDesc = "Temperature"; | ||
686 | pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP; | ||
687 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR; | ||
688 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN; | ||
689 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN; | ||
690 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR; | ||
691 | pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN; | ||
692 | break; | ||
693 | case 1: | ||
694 | pAC->I2c.SenTable[i].SenDesc = "Voltage PCI"; | ||
695 | pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; | ||
696 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR; | ||
697 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN; | ||
698 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN; | ||
699 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR; | ||
700 | pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN; | ||
701 | break; | ||
702 | case 2: | ||
703 | pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO"; | ||
704 | pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; | ||
705 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR; | ||
706 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN; | ||
707 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN; | ||
708 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR; | ||
709 | pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN; | ||
710 | pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO; | ||
711 | break; | ||
712 | case 3: | ||
713 | pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC"; | ||
714 | pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; | ||
715 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR; | ||
716 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN; | ||
717 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN; | ||
718 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR; | ||
719 | pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN; | ||
720 | break; | ||
721 | case 4: | ||
722 | if (pAC->GIni.GIGenesis) { | ||
723 | if (pPrt->PhyType == SK_PHY_BCOM) { | ||
724 | pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL"; | ||
725 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; | ||
726 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; | ||
727 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; | ||
728 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; | ||
729 | } | ||
730 | else { | ||
731 | pAC->I2c.SenTable[i].SenDesc = "Voltage PMA"; | ||
732 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; | ||
733 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; | ||
734 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; | ||
735 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; | ||
736 | } | ||
737 | } | ||
738 | else { | ||
739 | pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX"; | ||
740 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR; | ||
741 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN; | ||
742 | if (pAC->GIni.GIVauxAvail) { | ||
743 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; | ||
744 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; | ||
745 | } | ||
746 | else { | ||
747 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR; | ||
748 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR; | ||
749 | } | ||
750 | } | ||
751 | pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; | ||
752 | pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN; | ||
753 | break; | ||
754 | case 5: | ||
755 | if (pAC->GIni.GIGenesis) { | ||
756 | pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; | ||
757 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; | ||
758 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; | ||
759 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; | ||
760 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; | ||
761 | } | ||
762 | else { | ||
763 | pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5"; | ||
764 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; | ||
765 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; | ||
766 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; | ||
767 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR; | ||
768 | } | ||
769 | pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; | ||
770 | pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN; | ||
771 | break; | ||
772 | case 6: | ||
773 | if (pAC->GIni.GIGenesis) { | ||
774 | pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL"; | ||
775 | } | ||
776 | else { | ||
777 | pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3"; | ||
778 | } | ||
779 | pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; | ||
780 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; | ||
781 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; | ||
782 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; | ||
783 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; | ||
784 | pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN; | ||
785 | break; | ||
786 | case 7: | ||
787 | if (pAC->GIni.GIGenesis) { | ||
788 | pAC->I2c.SenTable[i].SenDesc = "Speed Fan"; | ||
789 | pAC->I2c.SenTable[i].SenType = SK_SEN_FAN; | ||
790 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR; | ||
791 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN; | ||
792 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN; | ||
793 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR; | ||
794 | pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; | ||
795 | } | ||
796 | else { | ||
797 | pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; | ||
798 | pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; | ||
799 | pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; | ||
800 | pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; | ||
801 | pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; | ||
802 | pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; | ||
803 | pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN; | ||
804 | } | ||
805 | break; | ||
806 | default: | ||
807 | SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW, | ||
808 | SKERR_I2C_E001, SKERR_I2C_E001MSG); | ||
809 | break; | ||
810 | } | ||
811 | |||
812 | pAC->I2c.SenTable[i].SenValue = 0; | ||
813 | pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; | ||
814 | pAC->I2c.SenTable[i].SenErrCts = 0; | ||
815 | pAC->I2c.SenTable[i].SenBegErrTS = 0; | ||
816 | pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; | ||
817 | pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor; | ||
818 | pAC->I2c.SenTable[i].SenDev = LM80_ADDR; | ||
819 | } | ||
820 | |||
821 | #ifndef SK_DIAG | ||
822 | pAC->I2c.DummyReads = pAC->I2c.MaxSens; | ||
823 | #endif /* !SK_DIAG */ | ||
824 | |||
825 | /* Clear I2C IRQ */ | ||
826 | SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); | ||
827 | |||
828 | /* Now we are I/O initialized */ | ||
829 | pAC->I2c.InitLevel = SK_INIT_IO; | ||
830 | return(0); | ||
831 | } /* SkI2cInit1 */ | ||
832 | |||
833 | |||
834 | /* | ||
835 | * Init level 2: Start first sensor read. | ||
836 | */ | ||
837 | static int SkI2cInit2( | ||
838 | SK_AC *pAC, /* Adapter Context */ | ||
839 | SK_IOC IoC) /* I/O Context */ | ||
840 | { | ||
841 | int ReadComplete; | ||
842 | SK_SENSOR *pSen; | ||
843 | |||
844 | if (pAC->I2c.InitLevel != SK_INIT_IO) { | ||
845 | /* ReInit not needed in I2C module */ | ||
846 | /* Init0 and Init2 not permitted */ | ||
847 | return(0); | ||
848 | } | ||
849 | |||
850 | pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; | ||
851 | ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); | ||
852 | |||
853 | if (ReadComplete) { | ||
854 | SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG); | ||
855 | } | ||
856 | |||
857 | /* Now we are correctly initialized */ | ||
858 | pAC->I2c.InitLevel = SK_INIT_RUN; | ||
859 | |||
860 | return(0); | ||
861 | } /* SkI2cInit2*/ | ||
862 | |||
863 | |||
864 | /* | ||
865 | * Initialize I2C devices | ||
866 | * | ||
867 | * Get the first voltage value and discard it. | ||
868 | * Go into temperature read mode. A default pointer is not set. | ||
869 | * | ||
870 | * The things to be done depend on the init level in the parameter list: | ||
871 | * Level 0: | ||
872 | * Initialize only the data structures. Do NOT access hardware. | ||
873 | * Level 1: | ||
874 | * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts. | ||
875 | * Level 2: | ||
876 | * Everything is possible. Interrupts may be used from now on. | ||
877 | * | ||
878 | * return: | ||
879 | * 0 = success | ||
880 | * other = error. | ||
881 | */ | ||
882 | int SkI2cInit( | ||
883 | SK_AC *pAC, /* Adapter Context */ | ||
884 | SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */ | ||
885 | int Level) /* Init Level */ | ||
886 | { | ||
887 | |||
888 | switch (Level) { | ||
889 | case SK_INIT_DATA: | ||
890 | return(SkI2cInit0(pAC)); | ||
891 | case SK_INIT_IO: | ||
892 | return(SkI2cInit1(pAC, IoC)); | ||
893 | case SK_INIT_RUN: | ||
894 | return(SkI2cInit2(pAC, IoC)); | ||
895 | default: | ||
896 | break; | ||
897 | } | ||
898 | |||
899 | return(0); | ||
900 | } /* SkI2cInit */ | ||
901 | |||
902 | |||
903 | #ifndef SK_DIAG | ||
904 | |||
905 | /* | ||
906 | * Interrupt service function for the I2C Interface | ||
907 | * | ||
908 | * Clears the Interrupt source | ||
909 | * | ||
910 | * Reads the register and check it for sending a trap. | ||
911 | * | ||
912 | * Starts the timer if necessary. | ||
913 | */ | ||
914 | void SkI2cIsr( | ||
915 | SK_AC *pAC, /* Adapter Context */ | ||
916 | SK_IOC IoC) /* I/O Context */ | ||
917 | { | ||
918 | SK_EVPARA Para; | ||
919 | |||
920 | /* Clear I2C IRQ */ | ||
921 | SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); | ||
922 | |||
923 | Para.Para64 = 0; | ||
924 | SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para); | ||
925 | } /* SkI2cIsr */ | ||
926 | |||
927 | |||
928 | /* | ||
929 | * Check this sensors Value against the threshold and send events. | ||
930 | */ | ||
931 | static void SkI2cCheckSensor( | ||
932 | SK_AC *pAC, /* Adapter Context */ | ||
933 | SK_SENSOR *pSen) | ||
934 | { | ||
935 | SK_EVPARA ParaLocal; | ||
936 | SK_BOOL TooHigh; /* Is sensor too high? */ | ||
937 | SK_BOOL TooLow; /* Is sensor too low? */ | ||
938 | SK_U64 CurrTime; /* Current Time */ | ||
939 | SK_BOOL DoTrapSend; /* We need to send a trap */ | ||
940 | SK_BOOL DoErrLog; /* We need to log the error */ | ||
941 | SK_BOOL IsError; /* We need to log the error */ | ||
942 | |||
943 | /* Check Dummy Reads first */ | ||
944 | if (pAC->I2c.DummyReads > 0) { | ||
945 | pAC->I2c.DummyReads--; | ||
946 | return; | ||
947 | } | ||
948 | |||
949 | /* Get the current time */ | ||
950 | CurrTime = SkOsGetTime(pAC); | ||
951 | |||
952 | /* Set para to the most useful setting: The current sensor. */ | ||
953 | ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens; | ||
954 | |||
955 | /* Check the Value against the thresholds. First: Error Thresholds */ | ||
956 | TooHigh = (pSen->SenValue > pSen->SenThreErrHigh); | ||
957 | TooLow = (pSen->SenValue < pSen->SenThreErrLow); | ||
958 | |||
959 | IsError = SK_FALSE; | ||
960 | if (TooHigh || TooLow) { | ||
961 | /* Error condition is satisfied */ | ||
962 | DoTrapSend = SK_TRUE; | ||
963 | DoErrLog = SK_TRUE; | ||
964 | |||
965 | /* Now error condition is satisfied */ | ||
966 | IsError = SK_TRUE; | ||
967 | |||
968 | if (pSen->SenErrFlag == SK_SEN_ERR_ERR) { | ||
969 | /* This state is the former one */ | ||
970 | |||
971 | /* So check first whether we have to send a trap */ | ||
972 | if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > | ||
973 | CurrTime) { | ||
974 | /* | ||
975 | * Do NOT send the Trap. The hold back time | ||
976 | * has to run out first. | ||
977 | */ | ||
978 | DoTrapSend = SK_FALSE; | ||
979 | } | ||
980 | |||
981 | /* Check now whether we have to log an Error */ | ||
982 | if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > | ||
983 | CurrTime) { | ||
984 | /* | ||
985 | * Do NOT log the error. The hold back time | ||
986 | * has to run out first. | ||
987 | */ | ||
988 | DoErrLog = SK_FALSE; | ||
989 | } | ||
990 | } | ||
991 | else { | ||
992 | /* We came from a different state -> Set Begin Time Stamp */ | ||
993 | pSen->SenBegErrTS = CurrTime; | ||
994 | pSen->SenErrFlag = SK_SEN_ERR_ERR; | ||
995 | } | ||
996 | |||
997 | if (DoTrapSend) { | ||
998 | /* Set current Time */ | ||
999 | pSen->SenLastErrTrapTS = CurrTime; | ||
1000 | pSen->SenErrCts++; | ||
1001 | |||
1002 | /* Queue PNMI Event */ | ||
1003 | SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? | ||
1004 | SK_PNMI_EVT_SEN_ERR_UPP : | ||
1005 | SK_PNMI_EVT_SEN_ERR_LOW), | ||
1006 | ParaLocal); | ||
1007 | } | ||
1008 | |||
1009 | if (DoErrLog) { | ||
1010 | /* Set current Time */ | ||
1011 | pSen->SenLastErrLogTS = CurrTime; | ||
1012 | |||
1013 | if (pSen->SenType == SK_SEN_TEMP) { | ||
1014 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG); | ||
1015 | } | ||
1016 | else if (pSen->SenType == SK_SEN_VOLT) { | ||
1017 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG); | ||
1018 | } | ||
1019 | else { | ||
1020 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG); | ||
1021 | } | ||
1022 | } | ||
1023 | } | ||
1024 | |||
1025 | /* Check the Value against the thresholds */ | ||
1026 | /* 2nd: Warning thresholds */ | ||
1027 | TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh); | ||
1028 | TooLow = (pSen->SenValue < pSen->SenThreWarnLow); | ||
1029 | |||
1030 | if (!IsError && (TooHigh || TooLow)) { | ||
1031 | /* Error condition is satisfied */ | ||
1032 | DoTrapSend = SK_TRUE; | ||
1033 | DoErrLog = SK_TRUE; | ||
1034 | |||
1035 | if (pSen->SenErrFlag == SK_SEN_ERR_WARN) { | ||
1036 | /* This state is the former one */ | ||
1037 | |||
1038 | /* So check first whether we have to send a trap */ | ||
1039 | if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) { | ||
1040 | /* | ||
1041 | * Do NOT send the Trap. The hold back time | ||
1042 | * has to run out first. | ||
1043 | */ | ||
1044 | DoTrapSend = SK_FALSE; | ||
1045 | } | ||
1046 | |||
1047 | /* Check now whether we have to log an Error */ | ||
1048 | if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) { | ||
1049 | /* | ||
1050 | * Do NOT log the error. The hold back time | ||
1051 | * has to run out first. | ||
1052 | */ | ||
1053 | DoErrLog = SK_FALSE; | ||
1054 | } | ||
1055 | } | ||
1056 | else { | ||
1057 | /* We came from a different state -> Set Begin Time Stamp */ | ||
1058 | pSen->SenBegWarnTS = CurrTime; | ||
1059 | pSen->SenErrFlag = SK_SEN_ERR_WARN; | ||
1060 | } | ||
1061 | |||
1062 | if (DoTrapSend) { | ||
1063 | /* Set current Time */ | ||
1064 | pSen->SenLastWarnTrapTS = CurrTime; | ||
1065 | pSen->SenWarnCts++; | ||
1066 | |||
1067 | /* Queue PNMI Event */ | ||
1068 | SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? | ||
1069 | SK_PNMI_EVT_SEN_WAR_UPP : | ||
1070 | SK_PNMI_EVT_SEN_WAR_LOW), | ||
1071 | ParaLocal); | ||
1072 | } | ||
1073 | |||
1074 | if (DoErrLog) { | ||
1075 | /* Set current Time */ | ||
1076 | pSen->SenLastWarnLogTS = CurrTime; | ||
1077 | |||
1078 | if (pSen->SenType == SK_SEN_TEMP) { | ||
1079 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG); | ||
1080 | } | ||
1081 | else if (pSen->SenType == SK_SEN_VOLT) { | ||
1082 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG); | ||
1083 | } | ||
1084 | else { | ||
1085 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG); | ||
1086 | } | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | /* Check for NO error at all */ | ||
1091 | if (!IsError && !TooHigh && !TooLow) { | ||
1092 | /* Set o.k. Status if no error and no warning condition */ | ||
1093 | pSen->SenErrFlag = SK_SEN_ERR_OK; | ||
1094 | } | ||
1095 | |||
1096 | /* End of check against the thresholds */ | ||
1097 | |||
1098 | /* Bug fix AF: 16.Aug.2001: Correct the init base | ||
1099 | * of LM80 sensor. | ||
1100 | */ | ||
1101 | if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) { | ||
1102 | |||
1103 | pSen->SenInit = SK_SEN_DYN_INIT_NONE; | ||
1104 | |||
1105 | if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) { | ||
1106 | /* 5V PCI-IO Voltage */ | ||
1107 | pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN; | ||
1108 | pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR; | ||
1109 | } | ||
1110 | else { | ||
1111 | /* 3.3V PCI-IO Voltage */ | ||
1112 | pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN; | ||
1113 | pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR; | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | #ifdef TEST_ONLY | ||
1118 | /* Dynamic thresholds also for VAUX of LM80 sensor */ | ||
1119 | if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) { | ||
1120 | |||
1121 | pSen->SenInit = SK_SEN_DYN_INIT_NONE; | ||
1122 | |||
1123 | /* 3.3V VAUX Voltage */ | ||
1124 | if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) { | ||
1125 | pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; | ||
1126 | pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; | ||
1127 | } | ||
1128 | /* 0V VAUX Voltage */ | ||
1129 | else { | ||
1130 | pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR; | ||
1131 | pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR; | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | /* | ||
1136 | * Check initialization state: | ||
1137 | * The VIO Thresholds need adaption | ||
1138 | */ | ||
1139 | if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && | ||
1140 | pSen->SenValue > SK_SEN_WARNLOW2C && | ||
1141 | pSen->SenValue < SK_SEN_WARNHIGH2) { | ||
1142 | pSen->SenThreErrLow = SK_SEN_ERRLOW2C; | ||
1143 | pSen->SenThreWarnLow = SK_SEN_WARNLOW2C; | ||
1144 | pSen->SenInit = SK_TRUE; | ||
1145 | } | ||
1146 | |||
1147 | if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && | ||
1148 | pSen->SenValue > SK_SEN_WARNLOW2 && | ||
1149 | pSen->SenValue < SK_SEN_WARNHIGH2C) { | ||
1150 | pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C; | ||
1151 | pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C; | ||
1152 | pSen->SenInit = SK_TRUE; | ||
1153 | } | ||
1154 | #endif | ||
1155 | |||
1156 | if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) { | ||
1157 | SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG); | ||
1158 | } | ||
1159 | } /* SkI2cCheckSensor */ | ||
1160 | |||
1161 | |||
1162 | /* | ||
1163 | * The only Event to be served is the timeout event | ||
1164 | * | ||
1165 | */ | ||
1166 | int SkI2cEvent( | ||
1167 | SK_AC *pAC, /* Adapter Context */ | ||
1168 | SK_IOC IoC, /* I/O Context */ | ||
1169 | SK_U32 Event, /* Module specific Event */ | ||
1170 | SK_EVPARA Para) /* Event specific Parameter */ | ||
1171 | { | ||
1172 | int ReadComplete; | ||
1173 | SK_SENSOR *pSen; | ||
1174 | SK_U32 Time; | ||
1175 | SK_EVPARA ParaLocal; | ||
1176 | int i; | ||
1177 | |||
1178 | /* New case: no sensors */ | ||
1179 | if (pAC->I2c.MaxSens == 0) { | ||
1180 | return(0); | ||
1181 | } | ||
1182 | |||
1183 | switch (Event) { | ||
1184 | case SK_I2CEV_IRQ: | ||
1185 | pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; | ||
1186 | ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); | ||
1187 | |||
1188 | if (ReadComplete) { | ||
1189 | /* Check sensor against defined thresholds */ | ||
1190 | SkI2cCheckSensor(pAC, pSen); | ||
1191 | |||
1192 | /* Increment Current sensor and set appropriate Timeout */ | ||
1193 | pAC->I2c.CurrSens++; | ||
1194 | if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) { | ||
1195 | pAC->I2c.CurrSens = 0; | ||
1196 | Time = SK_I2C_TIM_LONG; | ||
1197 | } | ||
1198 | else { | ||
1199 | Time = SK_I2C_TIM_SHORT; | ||
1200 | } | ||
1201 | |||
1202 | /* Start Timer */ | ||
1203 | ParaLocal.Para64 = (SK_U64)0; | ||
1204 | |||
1205 | pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; | ||
1206 | |||
1207 | SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, | ||
1208 | SKGE_I2C, SK_I2CEV_TIM, ParaLocal); | ||
1209 | } | ||
1210 | else { | ||
1211 | /* Start Timer */ | ||
1212 | ParaLocal.Para64 = (SK_U64)0; | ||
1213 | |||
1214 | pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; | ||
1215 | |||
1216 | SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH, | ||
1217 | SKGE_I2C, SK_I2CEV_TIM, ParaLocal); | ||
1218 | } | ||
1219 | break; | ||
1220 | case SK_I2CEV_TIM: | ||
1221 | if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) { | ||
1222 | |||
1223 | ParaLocal.Para64 = (SK_U64)0; | ||
1224 | SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer); | ||
1225 | |||
1226 | pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; | ||
1227 | ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); | ||
1228 | |||
1229 | if (ReadComplete) { | ||
1230 | /* Check sensor against defined thresholds */ | ||
1231 | SkI2cCheckSensor(pAC, pSen); | ||
1232 | |||
1233 | /* Increment Current sensor and set appropriate Timeout */ | ||
1234 | pAC->I2c.CurrSens++; | ||
1235 | if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { | ||
1236 | pAC->I2c.CurrSens = 0; | ||
1237 | Time = SK_I2C_TIM_LONG; | ||
1238 | } | ||
1239 | else { | ||
1240 | Time = SK_I2C_TIM_SHORT; | ||
1241 | } | ||
1242 | |||
1243 | /* Start Timer */ | ||
1244 | ParaLocal.Para64 = (SK_U64)0; | ||
1245 | |||
1246 | pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; | ||
1247 | |||
1248 | SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, | ||
1249 | SKGE_I2C, SK_I2CEV_TIM, ParaLocal); | ||
1250 | } | ||
1251 | } | ||
1252 | else { | ||
1253 | pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; | ||
1254 | pSen->SenErrFlag = SK_SEN_ERR_FAULTY; | ||
1255 | SK_I2C_STOP(IoC); | ||
1256 | |||
1257 | /* Increment Current sensor and set appropriate Timeout */ | ||
1258 | pAC->I2c.CurrSens++; | ||
1259 | if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { | ||
1260 | pAC->I2c.CurrSens = 0; | ||
1261 | Time = SK_I2C_TIM_LONG; | ||
1262 | } | ||
1263 | else { | ||
1264 | Time = SK_I2C_TIM_SHORT; | ||
1265 | } | ||
1266 | |||
1267 | /* Start Timer */ | ||
1268 | ParaLocal.Para64 = (SK_U64)0; | ||
1269 | |||
1270 | pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; | ||
1271 | |||
1272 | SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, | ||
1273 | SKGE_I2C, SK_I2CEV_TIM, ParaLocal); | ||
1274 | } | ||
1275 | break; | ||
1276 | case SK_I2CEV_CLEAR: | ||
1277 | for (i = 0; i < SK_MAX_SENSORS; i++) { | ||
1278 | pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; | ||
1279 | pAC->I2c.SenTable[i].SenErrCts = 0; | ||
1280 | pAC->I2c.SenTable[i].SenWarnCts = 0; | ||
1281 | pAC->I2c.SenTable[i].SenBegErrTS = 0; | ||
1282 | pAC->I2c.SenTable[i].SenBegWarnTS = 0; | ||
1283 | pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0; | ||
1284 | pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0; | ||
1285 | pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0; | ||
1286 | pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0; | ||
1287 | } | ||
1288 | break; | ||
1289 | default: | ||
1290 | SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG); | ||
1291 | } | ||
1292 | |||
1293 | return(0); | ||
1294 | } /* SkI2cEvent*/ | ||
1295 | |||
1296 | #endif /* !SK_DIAG */ | ||