/***************************************************************************
                          w747_i2c_function.c  -  description
                             -------------------
    begin                : 11¤ë 23 ¤é2004
    copyright            : (C) 2004 by root
    email                : 
 ***************************************************************************/ 

#include <linux/delay.h>
#include <asm/io.h>
#include <asm/web777.h>

#include "w747_i2c_function.h"
#include "w747_i2c.h"

//----------------------------------------------------------------------
void w747_init_i2c(unsigned int config, unsigned int clkdiv)
{
    outl_p(config, W747_I2C_CONFIG_REG);
    outl_p(clkdiv, W747_I2C_CLKDIV_REG);
}

int w747_set_i2c_dev_adr(unsigned char addr)
{
    outl_p(addr, W747_I2C_DEVADR_REG);
    return 0;
}

void w747_i2c_wr_delay(unsigned int delay)
{  
    unsigned int delay_cnt;
    for(delay_cnt = 0; delay_cnt < delay; delay_cnt++) { };
}

int w747_status_poll(unsigned int expected_value, unsigned int index, unsigned int time_out)
{
  unsigned int status;
  unsigned int masked_status, ackerr;
  unsigned int cnt = 0;

  do {
    //status = *(unsigned int *) MAP_I2C_STATUS;
    status = inl_p(W747_I2C_STATUS_REG);
    ackerr = status & 0x8;
    masked_status = status & expected_value;
    cnt++;
  } while ((masked_status != expected_value) && (cnt != time_out));

  if(ackerr)
  {
     MSG("!!! I2C ACK ERROR, Slave Not Responding !!! read %x, expected %x, index %x \n", 
		   status, expected_value, index);
     return 1;
  }

  if(cnt == time_out)
  { 
     MSG("!!! I2C STATUS TIMEOUT !!! read %x, expected %x, index %x \n", 
		   status, expected_value, index);
     return 1;
  }
  return 0;
}

int w747_i2c_write_single(unsigned int addr, unsigned int data, unsigned int dev_type)
{
    int rc = 0;
    unsigned int addr_msb = (addr >> 8) & 0xff;
    unsigned int addr_lsb = (addr & 0xff);

    outl_p(0x02, W747_I2C_BYTCNT_REG);
    
    if(dev_type == TYPE_THERMAL){
        /* addr tx       */
        /* -------       */
        outl_p(addr_lsb, W747_I2C_DATAOUT_REG);
        outl_p(0x00, W747_I2C_SDEN_REG);
        rc = w747_status_poll(0x02,0x1,I2C_STATUS_TIMEOUT);

        /* data tx       */
        /* -------       */
        outl_p(((data >> 8) & 0xff), W747_I2C_DATAOUT_REG); 
        if (!rc)
            rc = w747_status_poll(0x02,0x2,I2C_STATUS_TIMEOUT);

        outl_p((data & 0xff), W747_I2C_DATAOUT_REG);  
    }//thermal
    else{
        /* addr tx       */
        /* -------       */
        outl_p(addr_msb, W747_I2C_DATAOUT_REG);
        outl_p(0x00, W747_I2C_SDEN_REG);
        rc = w747_status_poll(0x02,0x1,I2C_STATUS_TIMEOUT);

        outl_p(addr_lsb, W747_I2C_DATAOUT_REG); 
        if (!rc)
            rc = w747_status_poll(0x02,0x2,I2C_STATUS_TIMEOUT);

        /* data tx       */
        /* -------       */
        outl_p(data, W747_I2C_DATAOUT_REG);  
    }//eeprom
    
    if (!rc)
        rc = w747_status_poll(0x03,0x3,I2C_STATUS_TIMEOUT);

    /* delay before next access         */
    /* ------------------------         */
    w747_i2c_wr_delay(WR_DELAY);
    return rc;
}

int w747_i2c_read_single(unsigned int addr, unsigned int *val, unsigned int dev_type)
{
   unsigned int data;
   int rc = 0;
   unsigned int addr_msb = (addr >> 8) & 0xff;
   unsigned int addr_lsb = (addr & 0xff);

   if(dev_type == TYPE_THERMAL){
      /* addr tx       */
      /* -------       */
      outl_p(0x00, W747_I2C_BYTCNT_REG);  
      outl_p(addr_lsb, W747_I2C_DATAOUT_REG);  
      outl_p(0x00, W747_I2C_SDEN_REG);  

      rc = w747_status_poll(0x03,0x5,I2C_STATUS_TIMEOUT);        

      outl_p(0x01, W747_I2C_BYTCNT_REG);

      /* data rx & check       */
      /* ---------------       */
      outl_p(0x01, W747_I2C_SDEN_REG); 
      if (!rc)
          rc = w747_status_poll(0x04,0x6,I2C_STATUS_TIMEOUT);
      data = inl_p(W747_I2C_DATAIN_REG) << 8;   
      if (!rc)
          rc = w747_status_poll(0x04,0x6,I2C_STATUS_TIMEOUT);
      data = (data & 0xff00) | inl_p(W747_I2C_DATAIN_REG);         	
   }//thermal
   else{
      /* addr tx       */
      /* -------       */
      outl_p(0x01, W747_I2C_BYTCNT_REG);  
      outl_p(addr_msb, W747_I2C_DATAOUT_REG);  
      outl_p(0x00, W747_I2C_SDEN_REG);  
   
      rc = w747_status_poll(0x02,0x4,I2C_STATUS_TIMEOUT); 
          
      outl_p(addr_lsb, W747_I2C_DATAOUT_REG);
      if (!rc)
          rc = w747_status_poll(0x03,0x5,I2C_STATUS_TIMEOUT);        

      outl_p(0x00, W747_I2C_BYTCNT_REG);

      /* data rx & check       */
      /* ---------------       */
      outl_p(0x01, W747_I2C_SDEN_REG); 
      if (!rc)
          rc = w747_status_poll(0x04,0x6,I2C_STATUS_TIMEOUT);
      data = inl_p(W747_I2C_DATAIN_REG);
   }//eeprom
   
   if (!rc)
     rc = w747_status_poll(0x03,0x7,I2C_STATUS_TIMEOUT);

   *val = data;
   return rc;
}





