1 /******************************************************************************
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
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect.
14 * (C)Copyright 2002-2003 Marvell.
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.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
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. ";
33 #include "h/skdrv1st.h" /* Driver Specific Definitions */
35 #include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
39 I2C protocol implementation.
43 The I2C protocol is used for the temperature sensors and for
44 the serial EEPROM which hold the configuration.
46 This file covers functions that allow to read write and do
47 some bulk requests a specified I2C address.
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.
54 Note: The VPD functions are in skvpd.c
56 . PCI Config I2C Bus for VPD Data:
64 . +-----------+-----------+
66 . +-----------------+ +-----------------+
67 . | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG |
68 . +-----------------+ +-----------------+
71 . I2C Bus for LM80 sensor:
83 . +-------------->| OR |<--+
87 . +--------+ +--------+ +----------+
88 . | B2_I2C | | B2_I2C | | B2_I2C |
89 . | _CTRL | | _DATA | | _SW |
90 . +--------+ +--------+ +----------+
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.
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
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
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.
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 */
136 #define NS2BCLK(x) (((x)*125)/10000)
139 * I2C Wire Operations
141 * About I2C_CLK_LOW():
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.
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)
156 #define NS2CLKT(x) ((x*125L)/10000)
158 /*--------------- I2C Interface Register Functions --------------- */
164 SK_IOC IoC, /* I/O Context */
165 SK_U8 Bit) /* Bit to send */
174 SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
176 SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
182 * Signal a start to the I2C Bus.
184 * A start is signaled when data goes to low in a high clock cycle.
186 * Ends with Clock Low.
191 SK_IOC IoC) /* I/O Context */
193 /* Init data and Clock to output lines */
200 SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
205 SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
207 /* Clock low without Data to Input */
210 SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
215 SK_IOC IoC) /* I/O Context */
217 /* Init data and Clock to output lines */
222 SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
227 SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
230 * Set Data High: Do it by setting the Data Line to Input.
231 * Because of a pull up resistor the Data Line
237 * When I2C activity is stopped
238 * o DATA should be set to input and
239 * o CLOCK should be set to high!
241 SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
246 * Receive just one bit via the I2C bus.
248 * Note: Clock must be set to LOW before calling this function.
250 * Returns The received bit.
253 SK_IOC IoC) /* I/O Context */
258 /* Init data as input line */
261 SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
265 SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
267 SK_I2C_GET_SW(IoC, &I2cSwCtrl);
269 Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
272 SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
281 * returns 0 If acknowledged
282 * 1 in case of an error
285 SK_IOC IoC) /* I/O Context */
288 * Received bit must be zero.
290 return(SkI2cRcvBit(IoC) != 0);
298 SK_IOC IoC) /* I/O Context */
301 * Received bit must be zero.
311 SK_IOC IoC) /* I/O Context */
314 * Received bit must be zero.
321 * Send one byte to the I2C device and wait for ACK.
323 * Return acknowleged status.
326 SK_IOC IoC, /* I/O Context */
327 int Byte) /* byte to send */
331 for (i = 0; i < 8; i++) {
332 if (Byte & (1<<(7-i))) {
340 return(SkI2cRcvAck(IoC));
345 * Receive one byte and ack it.
350 SK_IOC IoC, /* I/O Context */
351 int Last) /* Last Byte Flag */
356 for (i = 0; i < 8; i++) {
358 Byte |= SkI2cRcvBit(IoC);
373 * Start dialog and send device address
375 * Return 0 if acknowleged, 1 in case of an error
378 SK_IOC IoC, /* I/O Context */
379 int Addr, /* Device Address */
380 int Rw) /* Read / Write Flag */
385 return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
390 /*----------------- I2C CTRL Register Functions ----------*/
393 * waits for a completion of an I2C transfer
395 * returns 0: success, transfer completes
396 * 1: error, transfer does not complete, I2C transfer
397 * killed, wait loop terminated.
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) */
408 StartTime = SkOsGetTime(pAC);
411 CurrentTime = SkOsGetTime(pAC);
413 if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
417 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
418 #endif /* !SK_DIAG */
422 SK_I2C_GET_CTL(IoC, &I2cCtrl);
425 printf("StartTime=%lu, CurrentTime=%lu\n",
426 StartTime, CurrentTime);
430 #endif /* YUKON_DBG */
432 } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
439 * waits for a completion of an I2C transfer
445 SK_AC *pAC, /* Adapter Context */
446 SK_IOC IoC) /* I/O Context */
452 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
454 if (pSen->SenState == SK_SEN_IDLE) {
458 StartTime = SkOsGetTime(pAC);
461 if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
465 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
466 #endif /* !SK_DIAG */
470 SK_IN32(IoC, B0_ISRC, &IrqSrc);
472 } while ((IrqSrc & IS_I2C_READY) == 0);
474 pSen->SenState = SK_SEN_IDLE;
479 * writes a single byte or 4 bytes into the I2C device
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 */
493 SK_OUT32(IoC, B2_I2C_DATA, I2cData);
495 SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
497 return(SkI2cWait(pAC, IoC, I2C_WRITE));
503 * reads a single byte or 4 bytes from the I2C device
505 * returns the word read
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 */
517 SK_OUT32(IoC, B2_I2C_DATA, 0);
518 SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
520 if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
521 w_print("%s\n", SKERR_I2C_E002MSG);
524 SK_IN32(IoC, B2_I2C_DATA, &Data);
532 * read a sensor's value
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
538 * 1 if the read is completed
539 * 0 if the read must be continued (I2C Bus still allocated)
542 SK_AC *pAC, /* Adapter Context */
543 SK_IOC IoC, /* I/O Context */
544 SK_SENSOR *pSen) /* Sensor to be read */
546 if (pSen->SenRead != NULL) {
547 return((*pSen->SenRead)(pAC, IoC, pSen));
550 return(0); /* no success */
552 } /* SkI2cReadSensor */
555 * Do the Init state 0 initialization
557 static int SkI2cInit0(
558 SK_AC *pAC) /* Adapter Context */
562 /* Begin with first sensor */
563 pAC->I2c.CurrSens = 0;
565 /* Begin with timeout control for state machine */
566 pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
568 /* Set sensor number to zero */
569 pAC->I2c.MaxSens = 0;
572 /* Initialize Number of Dummy Reads */
573 pAC->I2c.DummyReads = SK_MAX_SENSORS;
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;
594 /* Now we are "INIT data"ed */
595 pAC->I2c.InitLevel = SK_INIT_DATA;
601 * Do the init state 1 initialization
603 * initialize the following register of the LM80:
604 * Configuration register:
605 * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
607 * Interrupt Mask Register 1:
608 * - all interrupts are Disabled (0xff)
610 * Interrupt Mask Register 2:
611 * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
613 * Fan Divisor/RST_OUT register:
614 * - Divisors set to 1 (bits 00), all others 0s.
616 * OS# Configuration/Temperature resolution Register:
620 static int SkI2cInit1(
621 SK_AC *pAC, /* Adapter Context */
622 SK_IOC IoC) /* I/O Context */
626 SK_GEPORT *pPrt; /* GIni Port struct pointer */
628 if (pAC->I2c.InitLevel != SK_INIT_DATA) {
629 /* ReInit not needed in I2C module */
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);
638 if ((I2cSwCtrl & I2C_DATA) == 0) {
639 /* this is a 32-Bit board */
640 pAC->GIni.GIYukon32Bit = SK_TRUE;
644 /* Check for 64 Bit Yukon without sensors */
645 if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
649 (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
651 (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
653 (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
655 (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
657 (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
661 * MaxSens has to be updated here, because PhyType is not
662 * set when performing Init Level 0
664 pAC->I2c.MaxSens = 5;
666 pPrt = &pAC->GIni.GP[0];
668 if (pAC->GIni.GIGenesis) {
669 if (pPrt->PhyType == SK_PHY_BCOM) {
670 if (pAC->GIni.GIMacsFound == 1) {
671 pAC->I2c.MaxSens += 1;
674 pAC->I2c.MaxSens += 3;
679 pAC->I2c.MaxSens += 3;
682 for (i = 0; i < pAC->I2c.MaxSens; i++) {
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;
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;
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;
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;
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;
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;
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;
747 pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
748 pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
751 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
752 pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
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;
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;
769 pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
770 pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
773 if (pAC->GIni.GIGenesis) {
774 pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
777 pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
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;
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;
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;
807 SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
808 SKERR_I2C_E001, SKERR_I2C_E001MSG);
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;
822 pAC->I2c.DummyReads = pAC->I2c.MaxSens;
823 #endif /* !SK_DIAG */
826 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
828 /* Now we are I/O initialized */
829 pAC->I2c.InitLevel = SK_INIT_IO;
835 * Init level 2: Start first sensor read.
837 static int SkI2cInit2(
838 SK_AC *pAC, /* Adapter Context */
839 SK_IOC IoC) /* I/O Context */
844 if (pAC->I2c.InitLevel != SK_INIT_IO) {
845 /* ReInit not needed in I2C module */
846 /* Init0 and Init2 not permitted */
850 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
851 ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
854 SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
857 /* Now we are correctly initialized */
858 pAC->I2c.InitLevel = SK_INIT_RUN;
865 * Initialize I2C devices
867 * Get the first voltage value and discard it.
868 * Go into temperature read mode. A default pointer is not set.
870 * The things to be done depend on the init level in the parameter list:
872 * Initialize only the data structures. Do NOT access hardware.
874 * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
876 * Everything is possible. Interrupts may be used from now on.
883 SK_AC *pAC, /* Adapter Context */
884 SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */
885 int Level) /* Init Level */
890 return(SkI2cInit0(pAC));
892 return(SkI2cInit1(pAC, IoC));
894 return(SkI2cInit2(pAC, IoC));
906 * Interrupt service function for the I2C Interface
908 * Clears the Interrupt source
910 * Reads the register and check it for sending a trap.
912 * Starts the timer if necessary.
915 SK_AC *pAC, /* Adapter Context */
916 SK_IOC IoC) /* I/O Context */
921 SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
924 SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
929 * Check this sensors Value against the threshold and send events.
931 static void SkI2cCheckSensor(
932 SK_AC *pAC, /* Adapter Context */
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 */
943 /* Check Dummy Reads first */
944 if (pAC->I2c.DummyReads > 0) {
945 pAC->I2c.DummyReads--;
949 /* Get the current time */
950 CurrTime = SkOsGetTime(pAC);
952 /* Set para to the most useful setting: The current sensor. */
953 ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
955 /* Check the Value against the thresholds. First: Error Thresholds */
956 TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
957 TooLow = (pSen->SenValue < pSen->SenThreErrLow);
960 if (TooHigh || TooLow) {
961 /* Error condition is satisfied */
962 DoTrapSend = SK_TRUE;
965 /* Now error condition is satisfied */
968 if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
969 /* This state is the former one */
971 /* So check first whether we have to send a trap */
972 if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
975 * Do NOT send the Trap. The hold back time
976 * has to run out first.
978 DoTrapSend = SK_FALSE;
981 /* Check now whether we have to log an Error */
982 if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
985 * Do NOT log the error. The hold back time
986 * has to run out first.
992 /* We came from a different state -> Set Begin Time Stamp */
993 pSen->SenBegErrTS = CurrTime;
994 pSen->SenErrFlag = SK_SEN_ERR_ERR;
998 /* Set current Time */
999 pSen->SenLastErrTrapTS = CurrTime;
1002 /* Queue PNMI Event */
1003 SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
1004 SK_PNMI_EVT_SEN_ERR_UPP :
1005 SK_PNMI_EVT_SEN_ERR_LOW),
1010 /* Set current Time */
1011 pSen->SenLastErrLogTS = CurrTime;
1013 if (pSen->SenType == SK_SEN_TEMP) {
1014 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
1016 else if (pSen->SenType == SK_SEN_VOLT) {
1017 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
1020 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
1025 /* Check the Value against the thresholds */
1026 /* 2nd: Warning thresholds */
1027 TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
1028 TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
1030 if (!IsError && (TooHigh || TooLow)) {
1031 /* Error condition is satisfied */
1032 DoTrapSend = SK_TRUE;
1035 if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
1036 /* This state is the former one */
1038 /* So check first whether we have to send a trap */
1039 if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
1041 * Do NOT send the Trap. The hold back time
1042 * has to run out first.
1044 DoTrapSend = SK_FALSE;
1047 /* Check now whether we have to log an Error */
1048 if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
1050 * Do NOT log the error. The hold back time
1051 * has to run out first.
1053 DoErrLog = SK_FALSE;
1057 /* We came from a different state -> Set Begin Time Stamp */
1058 pSen->SenBegWarnTS = CurrTime;
1059 pSen->SenErrFlag = SK_SEN_ERR_WARN;
1063 /* Set current Time */
1064 pSen->SenLastWarnTrapTS = CurrTime;
1067 /* Queue PNMI Event */
1068 SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
1069 SK_PNMI_EVT_SEN_WAR_UPP :
1070 SK_PNMI_EVT_SEN_WAR_LOW),
1075 /* Set current Time */
1076 pSen->SenLastWarnLogTS = CurrTime;
1078 if (pSen->SenType == SK_SEN_TEMP) {
1079 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
1081 else if (pSen->SenType == SK_SEN_VOLT) {
1082 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
1085 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
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;
1096 /* End of check against the thresholds */
1098 /* Bug fix AF: 16.Aug.2001: Correct the init base
1101 if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
1103 pSen->SenInit = SK_SEN_DYN_INIT_NONE;
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;
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;
1118 /* Dynamic thresholds also for VAUX of LM80 sensor */
1119 if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
1121 pSen->SenInit = SK_SEN_DYN_INIT_NONE;
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;
1128 /* 0V VAUX Voltage */
1130 pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
1131 pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
1136 * Check initialization state:
1137 * The VIO Thresholds need adaption
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;
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;
1156 if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
1157 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
1159 } /* SkI2cCheckSensor */
1163 * The only Event to be served is the timeout event
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 */
1175 SK_EVPARA ParaLocal;
1178 /* New case: no sensors */
1179 if (pAC->I2c.MaxSens == 0) {
1185 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
1186 ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
1189 /* Check sensor against defined thresholds */
1190 SkI2cCheckSensor(pAC, pSen);
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;
1199 Time = SK_I2C_TIM_SHORT;
1203 ParaLocal.Para64 = (SK_U64)0;
1205 pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
1207 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
1208 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
1212 ParaLocal.Para64 = (SK_U64)0;
1214 pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
1216 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
1217 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
1221 if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
1223 ParaLocal.Para64 = (SK_U64)0;
1224 SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
1226 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
1227 ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
1230 /* Check sensor against defined thresholds */
1231 SkI2cCheckSensor(pAC, pSen);
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;
1240 Time = SK_I2C_TIM_SHORT;
1244 ParaLocal.Para64 = (SK_U64)0;
1246 pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
1248 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
1249 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
1253 pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
1254 pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
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;
1264 Time = SK_I2C_TIM_SHORT;
1268 ParaLocal.Para64 = (SK_U64)0;
1270 pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
1272 SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
1273 SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
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;
1290 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
1296 #endif /* !SK_DIAG */