diff options
Diffstat (limited to 'src/apm_i2c.c')
-rw-r--r-- | src/apm_i2c.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/apm_i2c.c b/src/apm_i2c.c new file mode 100644 index 0000000..dc250b1 --- /dev/null +++ b/src/apm_i2c.c @@ -0,0 +1,86 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_i2c.c,v 1.7 2002/01/25 21:55:55 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; +} |