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