117a48c7cSmrg
217a48c7cSmrg#ifdef HAVE_CONFIG_H
317a48c7cSmrg#include "config.h"
417a48c7cSmrg#endif
517a48c7cSmrg
617a48c7cSmrg#include "apm.h"
717a48c7cSmrg#include "apm_regs.h"
817a48c7cSmrg
917a48c7cSmrg/* Inline functions */
1017a48c7cSmrgstatic __inline__ void
1117a48c7cSmrgWaitForFifo(ApmPtr pApm, int slots)
1217a48c7cSmrg{
1317a48c7cSmrg  if (!pApm->UsePCIRetry) {
1417a48c7cSmrg    volatile int i;
1517a48c7cSmrg#define MAXLOOP 1000000
1617a48c7cSmrg
1717a48c7cSmrg    for(i = 0; i < MAXLOOP; i++) {
1817a48c7cSmrg      if ((STATUS_IOP() & STATUS_FIFO) >= slots)
1917a48c7cSmrg	break;
2017a48c7cSmrg    }
2117a48c7cSmrg    if (i == MAXLOOP) {
2217a48c7cSmrg      unsigned int status = STATUS_IOP();
2317a48c7cSmrg
2417a48c7cSmrg      WRXB_IOP(0x1FF, 0);
2517a48c7cSmrg      FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
2617a48c7cSmrg    }
2717a48c7cSmrg  }
2817a48c7cSmrg}
2917a48c7cSmrg
3017a48c7cSmrgstatic void
3117a48c7cSmrgApmI2CPutBits(I2CBusPtr b, int clock,  int data)
3217a48c7cSmrg{
3317a48c7cSmrg    unsigned int	reg;
3417a48c7cSmrg    unsigned char	lock;
3517a48c7cSmrg    ApmPtr pApm = ((ApmPtr)b->DriverPrivate.ptr);
3617a48c7cSmrg
3717a48c7cSmrg    lock = rdinx(pApm->xport, 0x10);
3817a48c7cSmrg    wrinx(pApm->xport, 0x10, 0x12);
3917a48c7cSmrg    WaitForFifo(pApm, 2);
4017a48c7cSmrg    reg = (RDXB_IOP(0xD0) & 0x07) | 0x60;
4117a48c7cSmrg    if(clock) reg |= 0x08;
4217a48c7cSmrg    if(data)  reg |= 0x10;
4317a48c7cSmrg    WRXB_IOP(0xD0, reg);
4417a48c7cSmrg    if (lock)
4517a48c7cSmrg	wrinx(pApm->xport, 0x10, 0);
4617a48c7cSmrg}
4717a48c7cSmrg
4817a48c7cSmrgstatic void
4917a48c7cSmrgApmI2CGetBits(I2CBusPtr b, int *clock, int *data)
5017a48c7cSmrg{
5117a48c7cSmrg    unsigned int	reg;
5217a48c7cSmrg    unsigned char	lock;
5317a48c7cSmrg    ApmPtr pApm = ((ApmPtr)b->DriverPrivate.ptr);
5417a48c7cSmrg    unsigned char	tmp;
5517a48c7cSmrg
5617a48c7cSmrg    lock = rdinx(pApm->xport, 0x10);
5717a48c7cSmrg    wrinx(pApm->xport, 0x10, 0x12);
5817a48c7cSmrg    WaitForFifo(pApm, 2);
5917a48c7cSmrg    tmp = RDXB_IOP(0xD0);
6017a48c7cSmrg    WRXB_IOP(0xD0, tmp & 0x07);
6117a48c7cSmrg    reg = STATUS_IOP();
6217a48c7cSmrg    *clock = (reg & STATUS_SCL) != 0;
6317a48c7cSmrg    *data  = (reg & STATUS_SDA) != 0;
6417a48c7cSmrg    if (lock)
6517a48c7cSmrg	wrinx(pApm->xport, 0x10, 0);
6617a48c7cSmrg}
6717a48c7cSmrg
6817a48c7cSmrgBool
6917a48c7cSmrgApmI2CInit(ScrnInfoPtr pScrn)
7017a48c7cSmrg{
7117a48c7cSmrg    APMDECL(pScrn);
7217a48c7cSmrg    I2CBusPtr I2CPtr;
7317a48c7cSmrg
7417a48c7cSmrg    I2CPtr = xf86CreateI2CBusRec();
7517a48c7cSmrg    if(!I2CPtr) return FALSE;
7617a48c7cSmrg
7717a48c7cSmrg    pApm->I2CPtr	= I2CPtr;
7817a48c7cSmrg
7917a48c7cSmrg    I2CPtr->BusName    = "Alliance bus";
8017a48c7cSmrg    I2CPtr->scrnIndex  = pScrn->scrnIndex;
8117a48c7cSmrg    I2CPtr->I2CPutBits = ApmI2CPutBits;
8217a48c7cSmrg    I2CPtr->I2CGetBits = ApmI2CGetBits;
8317a48c7cSmrg    I2CPtr->DriverPrivate.ptr = pApm;
8417a48c7cSmrg
8517a48c7cSmrg    if(!xf86I2CBusInit(I2CPtr))
8617a48c7cSmrg       return FALSE;
8717a48c7cSmrg
8817a48c7cSmrg    return TRUE;
8917a48c7cSmrg}
90