1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_i2c.c,v 1.6.4.1 2001/11/28 22:35:13 tsi Exp $ */
#include "apm.h"
#include "apm_regs.h"
/* Inline functions */
static __inline__ void
WaitForFifo(ApmPtr pApm, int slots)
{
if (!pApm->UsePCIRetry) {
volatile int i;
#define MAXLOOP 1000000
for(i = 0; i < MAXLOOP; i++) {
if ((STATUS_IOP() & STATUS_FIFO) >= slots)
break;
}
if (i == MAXLOOP) {
unsigned int status = STATUS_IOP();
WRXB_IOP(0x1FF, 0);
FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
}
}
}
static void
ApmI2CPutBits(I2CBusPtr b, int clock, int data)
{
unsigned int reg;
unsigned char lock;
ApmPtr pApm = ((ApmPtr)b->DriverPrivate.ptr);
lock = rdinx(pApm->xport, 0x10);
wrinx(pApm->xport, 0x10, 0x12);
WaitForFifo(pApm, 2);
reg = (RDXB_IOP(0xD0) & 0x07) | 0x60;
if(clock) reg |= 0x08;
if(data) reg |= 0x10;
WRXB_IOP(0xD0, reg);
if (lock)
wrinx(pApm->xport, 0x10, 0);
}
static void
ApmI2CGetBits(I2CBusPtr b, int *clock, int *data)
{
unsigned int reg;
unsigned char lock;
ApmPtr pApm = ((ApmPtr)b->DriverPrivate.ptr);
unsigned char tmp;
lock = rdinx(pApm->xport, 0x10);
wrinx(pApm->xport, 0x10, 0x12);
WaitForFifo(pApm, 2);
tmp = RDXB_IOP(0xD0);
WRXB_IOP(0xD0, tmp & 0x07);
reg = STATUS_IOP();
*clock = (reg & STATUS_SCL) != 0;
*data = (reg & STATUS_SDA) != 0;
if (lock)
wrinx(pApm->xport, 0x10, 0);
}
Bool
ApmI2CInit(ScrnInfoPtr pScrn)
{
APMDECL(pScrn);
I2CBusPtr I2CPtr;
I2CPtr = xf86CreateI2CBusRec();
if(!I2CPtr) return FALSE;
pApm->I2CPtr = I2CPtr;
I2CPtr->BusName = "Alliance bus";
I2CPtr->scrnIndex = pScrn->scrnIndex;
I2CPtr->I2CPutBits = ApmI2CPutBits;
I2CPtr->I2CGetBits = ApmI2CGetBits;
I2CPtr->DriverPrivate.ptr = pApm;
if(!xf86I2CBusInit(I2CPtr))
return FALSE;
return TRUE;
}
|