/*
** I2C interface
** =============
** (C) 2000 by Paolo Scaffardi (arsenio@tin.it)
** AIRVENT SAM s.p.a - RIMINI(ITALY)
**
*/

#ifndef _I2C_H_
#define _I2C_H_

int  i2c_read  (uchar *addr, int alen, uchar *buffer, int len);
int  i2c_write (uchar *addr, int alen, uchar *buffer, int len);
#if defined(CONFIG_MPC824X)
uchar i2c_reg_read  (uchar i2c_addr, uchar reg);
void  i2c_reg_write (uchar i2c_addr, uchar reg, uchar val);

/* initialize i2c usage */
void i2c_init(void);

/* schedule a send operation (uses 1 tx bd) */
int i2c_send(unsigned char address,
		unsigned char secondary_address,
		unsigned short size,
		unsigned char *dataout);

/* schedule a receive operation (uses 1 tx bd, 1 rx bd) */
int i2c_receive(unsigned char address,
		unsigned char secondary_address,
		unsigned short size_to_expect,
		unsigned char *datain);
#endif
#if defined(CONFIG_4xx) || defined(CONFIG_IOP480)

void i2c_init(void);
int  i2c_receive(unsigned char address,
		 unsigned short size_to_expect, unsigned char datain[] );
int  i2c_send(unsigned char address,
		 unsigned short size_to_send, unsigned char dataout[] );
int i2c_write_page(uchar *addr, int alen, uchar *data, int dlen, int dsize);
#endif

#if !defined(CONFIG_MPC824X) && !defined(CONFIG_4xx) && !defined(CONFIG_IOP480)/* !( CONFIG_4xx || CONFIG_IOP480) */

uchar i2c_reg_read  (uchar i2c_addr, uchar reg);
void  i2c_reg_write (uchar i2c_addr, uchar reg, uchar val);

typedef void (*i2c_ecb_t)(int, int);	/* error callback function */

/* This structure keeps track of the bd and buffer space usage. */
typedef struct i2c_state {
	int		rx_idx;		/* index   to next free Rx BD */
	int		tx_idx;		/* index   to next free Tx BD */
	void	       *rxbd;		/* pointer to next free Rx BD */
	void	       *txbd;		/* pointer to next free Tx BD */
	int		tx_space;	/* number  of Tx bytes left   */
	unsigned char  *tx_buf;		/* pointer to free Tx area    */
	i2c_ecb_t	err_cb;		/* error callback function    */
} i2c_state_t;

/* initialize i2c usage */
void i2c_init(int speed, int slaveaddr);

/* prepare a new io sequence */
void i2c_newio(i2c_state_t *state);

/* schedule a send operation (uses 1 tx bd) */
int i2c_send(i2c_state_t *state,
		unsigned char address,
		unsigned char secondary_address,
		unsigned int flags,
		unsigned short size,
		unsigned char *dataout);

/* schedule a receive operation (uses 1 tx bd, 1 rx bd) */
int i2c_receive(i2c_state_t *state,
		unsigned char address,
		unsigned char secondary_address,
		unsigned int flags,
		unsigned short size_to_expect,
		unsigned char *datain);

/* execute all scheduled operations */
int i2c_doio(i2c_state_t *state);

/* flags for i2c_send() and i2c_receive() */
#define I2CF_ENABLE_SECONDARY	0x01	/* secondary_address is valid		*/
#define I2CF_START_COND		0x02	/* tx: generate start condition		*/
#define I2CF_STOP_COND		0x04	/* tx: generate stop  condition		*/

/* return codes */
#define I2CERR_NO_BUFFERS	0x01	/* no more BDs or buffer space		*/
#define I2CERR_MSG_TOO_LONG	0x02	/* tried to send/receive to much data	*/
#define I2CERR_TIMEOUT		0x03	/* timeout in i2c_doio()		*/
#define I2CERR_QUEUE_EMPTY	0x04	/* i2c_doio called without send/receive */

/* error callback flags */
#define I2CECB_RX_ERR		0x10	/* this is a receive error		*/
#define     I2CECB_RX_ERR_OV	0x02	/* receive overrun error		*/
#define     I2CECB_RX_MASK	0x0f	/* mask for error bits			*/
#define I2CECB_TX_ERR		0x20	/* this is a transmit error		*/
#define     I2CECB_TX_CL	0x01	/* transmit collision error		*/
#define     I2CECB_TX_UN	0x02	/* transmit underflow error		*/
#define     I2CECB_TX_NAK	0x04	/* transmit no ack error		*/
#define     I2CECB_TX_MASK	0x0f	/* mask for error bits			*/
#define I2CECB_TIMEOUT		0x40	/* this is a timeout error		*/

#endif	/* CPCI405, AR405, WALNUT405 */

#define ERROR_I2C_NONE		0
#define ERROR_I2C_LENGTH	1

#define I2C_WRITE_BIT		0x00
#define I2C_READ_BIT		0x01

#define I2C_RXTX_LEN	128	/* maximum tx/rx buffer length */

#endif	/* _I2C_H_ */
