i2c_master.c 3.16 KB
Newer Older
1 2 3 4
#include <stdio.h>

#include "fdelay_lib.h"
#include "fdelay_private.h"
5
#include "fd_main_regs.h"
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


#define M_SDA_OUT(x) {							\
    if(x)								\
      fd_writel(fd_readl(FD_REG_I2CR) | FD_I2CR_SDA_OUT, FD_REG_I2CR); \
    else								\
      fd_writel(fd_readl(FD_REG_I2CR) & (~FD_I2CR_SDA_OUT), FD_REG_I2CR); \
      udelay(10);\
  }

#define M_SCL_OUT(x) {							\
    if(x)								\
      fd_writel(fd_readl(FD_REG_I2CR) | FD_I2CR_SCL_OUT, FD_REG_I2CR); \
    else								\
      fd_writel(fd_readl(FD_REG_I2CR) & (~FD_I2CR_SCL_OUT), FD_REG_I2CR); \
      udelay(10); \
  }

#define M_SDA_IN ((fd_readl(FD_REG_I2CR) & FD_I2CR_SDA_IN) ? 1 : 0)

static void mi2c_start(fdelay_device_t *dev)
{
	fd_decl_private(dev);
  M_SDA_OUT(0);
  M_SCL_OUT(0);
}

static void mi2c_repeat_start(fdelay_device_t *dev)
{
	fd_decl_private(dev);
  M_SDA_OUT(1);
  M_SCL_OUT(1);
  M_SDA_OUT(0);
  M_SCL_OUT(0);
}

static void mi2c_stop(fdelay_device_t *dev)
{
	fd_decl_private(dev);
  M_SDA_OUT(0);
  M_SCL_OUT(1);
  M_SDA_OUT(1);
}

 int mi2c_put_byte(fdelay_device_t *dev, unsigned char data)
{
	fd_decl_private(dev);
  char i;
  unsigned char ack;

  for (i=0;i<8;i++, data<<=1)
    {
      M_SDA_OUT(data&0x80);
      M_SCL_OUT(1);
      M_SCL_OUT(0);
    }

  M_SDA_OUT(1);
  M_SCL_OUT(1);

  ack = M_SDA_IN;	/* ack: sda is pulled low ->success.	 */

  M_SCL_OUT(0);
  M_SDA_OUT(0);

  return ack!=0 ? -1 : 0;
}

void mi2c_get_byte(fdelay_device_t *dev, unsigned char *data, int ack)
{
76
	fd_decl_private(dev)
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

  int i;
  unsigned char indata = 0;

  /* assert: scl is low */
  M_SCL_OUT(0);
  M_SDA_OUT(1);
  for (i=0;i<8;i++)
    {
      M_SCL_OUT(1);
      indata <<= 1;
      if ( M_SDA_IN ) indata |= 0x01;
      M_SCL_OUT(0);
    }

  M_SDA_OUT((ack ? 0 : 1));
  M_SCL_OUT(1);
  M_SCL_OUT(0);
  M_SDA_OUT(0);

  *data= indata;
}

void mi2c_init(fdelay_device_t *dev)
{
	fd_decl_private(dev);
103

104 105 106 107 108 109 110 111 112 113 114 115 116
	M_SCL_OUT(1);
	M_SDA_OUT(1);
}

void mi2c_scan(fdelay_device_t *dev)
{
 	int i;
 	for(i=0;i<256;i+=2)
 	{
 	 	mi2c_start(dev);
		if(!mi2c_put_byte(dev,i))
			printf("Found device at 0x%x\n", i>>1);
		mi2c_stop(dev);
117

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
 	}
}

int eeprom_read(fdelay_device_t *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
	int i;
	unsigned char c;
	for(i=0;i<size;i++)
	{
 	mi2c_start(dev);
	if(mi2c_put_byte(dev, i2c_addr << 1) < 0)
 	{
 	 	mi2c_stop(dev);
 	 	return -1;
  	}

	mi2c_put_byte(dev, (offset >> 8) & 0xff);
	mi2c_put_byte(dev, offset & 0xff);
	offset++;
	mi2c_stop(dev);
	mi2c_start(dev);
 	mi2c_put_byte(dev, (i2c_addr << 1) | 1);
	mi2c_get_byte(dev, &c, 0);
141
//	printf("readback: %x\n", c);
142 143 144 145 146 147 148 149 150 151
	*buf++ = c;
 	mi2c_stop(dev);
 	}
 	return size;
}

int eeprom_write(fdelay_device_t *dev, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
	int i, busy;
	for(i=0;i<size;i++)
152
	{
153
	 	mi2c_start(dev);
154

155 156 157 158 159 160 161 162 163 164 165 166
	 	if(mi2c_put_byte(dev, i2c_addr << 1) < 0)
	 	{
		 	mi2c_stop(dev);
	 	 	return -1;
	  	}

		mi2c_put_byte(dev, (offset >> 8) & 0xff);
		mi2c_put_byte(dev, offset & 0xff);
		mi2c_put_byte(dev, *buf++);
		offset++;
		mi2c_stop(dev);

167

168 169 170
		do /* wait until the chip becomes ready */
		{
            mi2c_start(dev);
171
			busy = mi2c_put_byte(dev, i2c_addr << 1);
172 173 174 175 176
			mi2c_stop(dev);
		} while(busy);

	}
 	return size;
177
}