/*
 * $QNXLicenseC:
 * Copyright 2015, QNX Software Systems.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You
 * may not reproduce, modify or distribute this software except in
 * compliance with the License. You may obtain a copy of the License
 * at: http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OF ANY KIND, either express or implied.
 *
 * This file may contain contributions from others, either as
 * contributors under the License or as licensors under other terms.
 * Please review this entire file for other proprietary rights or license
 * notices, as well as the QNX Development Suite License Guide at
 * http://licensing.qnx.com/license-guide/ for other information.
 * $
 */
#ifndef _I2C_LIB_H_INCLUDED
#define _I2C_LIB_H_INCLUDED

#ifndef _PLATFORM_H_INCLUDED
#include <sys/platform.h>
#endif


#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <hw/dvfs_api.h>

#define I2C_1 "/dev/i2c1"
#define I2C_8 "/dev/i2c8"
#define SC_TEMP "/dev/sc"


#define I2C_1_TMP112_ADDR  		0X48
#define I2C_1_EEPROM_ADDR  		0X57
#define I2C_1_FRAM_ADDR    		0X50

#define I2C_8_EEPROM_ADDR  		0X51
#define I2C_8_TMP117_ADDR  		0X49
#define I2C_8_INA3321_ADDR 		0X40
#define I2C_8_EEPROM_8R_ADDR 	0X52
#define I2C_8_EEPROM_12R_ADDR 	0X53

#define EEPROM_IN_BOARD 	1
#define EEPROM_OUT_BOARD 	2
#define EEPROM_8R			3
#define EEPROM_12R			4



typedef int     sci_mgr_rsrc_t;
typedef uint8_t sci_mgr_misc_temp_t;

/** Structure for passing data with DCMD commands:
 *              - IMX_DCMD_SC_MISC_SET_TEMP
 *              - IMX_DCMD_SC_MISC_GET_TEMP
 */
typedef struct _imx_dcmd_sc_misc_temp_t {
    sci_mgr_rsrc_t resource;         /**< Resource with sensor */
    sci_mgr_misc_temp_t temp;        /**< Alarm to set */
    int16_t celsius;                 /**< Whole part of temp to set */
    int8_t tenths;                   /**< Fractional part of temp to set */
} imx_dcmd_sc_misc_temp_t;


int16_t temperature_read(int fd, uint8_t reg, uint8_t slave_addr);

int eeprom_write_data(int fd, uint32_t regaddr, uint8_t tx_buf[],uint32_t len,uint8_t slave_addr);
int eeprom_read_data(int fd, uint32_t regaddr, uint8_t rx_buf[],uint32_t len,uint8_t slave_addr);

int imx8_write_fram(uint8_t tx_buf[], unsigned int len);
int imx8_read_fram(uint8_t rx_buf[], unsigned int len);

int imx8_read_eeprom(int board,uint8_t rx_buf[], unsigned int len);
int imx8_write_eeprom(int board,uint8_t tx_buf[], unsigned int len);

int imx8_i2c_init(void);
int imx8_release_i2c(void);
double imx8_read_tmp112(void);
double imx8_read_tmp117(void);
int imx8_cpu_temp_init(void);
int imx8_read_cpu_temp(void);

struct ina3221 {
	int channel_1_shunt; /*channel 1 current*/
	float channel_1_bus; /*channel 1 voltage*/
	int channel_2_shunt; /*channel 2 current*/
	float channel_2_bus; /*channel 2 voltage*/
	int channel_3_shunt; /*channel 3 current*/
	float channel_3_bus; /*channel 3 voltage*/
};


int imx8_read_ina3221(struct ina3221* ina3221);




#define I2CLIB_VERSION_MAJOR    1
#define I2CLIB_VERSION_MINOR    0
#define I2CLIB_REVISION         0

#include <_pack1.h>

typedef struct {
    unsigned char   major;
    unsigned char   minor;
    unsigned char   revision;
} i2c_libversion_t;

/*
 * These codes are returned by devctl DCMD_I2C_STATUS to provide the cause of
 * of a failed I2C transaction.
 */
typedef enum {
    I2C_STATUS_DONE      = 0x0001,   /* transaction completed (with or
                                        without error) */
    I2C_STATUS_ERROR     = 0x0002,   /* timeout/unknown error */
    I2C_STATUS_NACK      = 0x0010,   /* slave no-acknowledge */
    I2C_STATUS_ARBL      = 0x0020,   /* lost arbitration */
    I2C_STATUS_BUSY      = 0x0040,   /* timed out */
    I2C_STATUS_ABORT     = 0x0100,   /* transaction aborted */
    I2C_STATUS_ADDR_NACK = 0x0200,   /* I2C_STATUS_NACK is address NACK */
    I2C_STATUS_DATA_NACK = 0x0400    /* I2C_STATUS_NACK is data NACK */
} i2c_status_t;

#define MAX_I2C_ERROR     I2C_STATUS_DATA_NACK

typedef enum {
    I2C_ADDRFMT_10BIT   = 0x0001,
    I2C_ADDRFMT_7BIT    = 0x0002,
} i2c_addrfmt_t;

typedef enum {
    I2C_SPEED_STANDARD  = 0x0001,   /* up to 100 kbit/s */
    I2C_SPEED_FAST      = 0x0002,   /* up to 400 kbit/s */
    I2C_SPEED_HIGH      = 0x0004    /* up to 3.4 Mbit/s */
} i2c_speed_mode_t;

typedef struct {
    _Uint32t            speed_mode; /* supported speeds: I2C_SPEED_* */
    _Uint32t            addr_mode;  /* supported address fmts: I2C_ADDRFMT_* */
    _Uint32t            reserved[2];
} i2c_driver_info_t;

typedef struct {
    _Uint32t            addr;   /* I2C address */
    _Uint32t            fmt;    /* 7- or 10-bit format */
} i2c_addr_t;

typedef struct {
    i2c_addr_t          slave;  /* slave address */
    _Uint32t            len;    /* length of send data in bytes */
    _Uint32t            stop;   /* send stop when complete? (0=no, 1=yes) */
} i2c_send_t;

typedef struct {
    i2c_addr_t          slave;  /* slave address */
    _Uint32t            len;    /* length of receive data in bytes */
    _Uint32t            stop;   /* send stop when complete? (0=no, 1=yes) */
} i2c_recv_t;

typedef struct {
    i2c_addr_t          slave;      /* slave address */
    _Uint32t            send_len;   /* length of send data in bytes */
    _Uint32t            recv_len;   /* length of receive data in bytes */
    _Uint32t            stop;       /* set stop when complete? */
} i2c_sendrecv_t;

typedef struct {
    _Uint32t            len;    /* length of data to send/recv, in bytes
                                   (not including this header) */
    _Uint32t            stop;   /* send stop when complete? (0=no, 1=yes) */
} i2c_masterhdr_t;

#include <_packpop.h>

/*
 * Resource Manager Interface
 */

/*
 * The following devctls are used by a client application
 * to control the I2C interface.
 */

#include <devctl.h>
#define _DCMD_I2C   _DCMD_MISC

#define DCMD_I2C_SET_SLAVE_ADDR     __DIOT (_DCMD_I2C, 1, i2c_addr_t)
#define DCMD_I2C_SET_BUS_SPEED      __DIOT (_DCMD_I2C, 2, _Uint32t)
#define DCMD_I2C_MASTER_SEND        __DIOT (_DCMD_I2C, 3, i2c_masterhdr_t)
#define DCMD_I2C_MASTER_RECV        __DIOTF(_DCMD_I2C, 4, i2c_masterhdr_t)
#define DCMD_I2C_SEND               __DIOT (_DCMD_I2C, 5, i2c_send_t)
#define DCMD_I2C_RECV               __DIOTF(_DCMD_I2C, 6, i2c_recv_t)
#define DCMD_I2C_SENDRECV           __DIOTF(_DCMD_I2C, 7, i2c_sendrecv_t)
#define DCMD_I2C_LOCK               __DION (_DCMD_I2C, 8)
#define DCMD_I2C_UNLOCK             __DION (_DCMD_I2C, 9)
#define DCMD_I2C_DRIVER_INFO        __DIOF (_DCMD_I2C, 10, i2c_driver_info_t)
#define DCMD_I2C_GET_BUS_SPEED      __DIOF (_DCMD_I2C, 11, _Uint32t)
#define DCMD_I2C_BUS_RESET          __DION (_DCMD_I2C, 12)
#define DCMD_I2C_STATUS             __DIOF (_DCMD_I2C, 13, i2c_status_t)

/*
 * Hardware interface
 */
typedef struct {
    /* size of this structure */
    size_t size;

    /*
     * Return version information
     * Returns:
     * 0    success
     * -1   failure
     */
    int (*version_info)(i2c_libversion_t *version);

    /*
     * Initialize master interface.
     * Returns a handle that is passed to all other functions.
     * Returns:
     * !NULL    success
     * NULL     failure
     */
    void *(*init)(int argc, char *argv[]);

    /*
     * Clean up driver.
     * Frees memory associated with "hdl".
     */
    void (*fini)(void *hdl);

    /*
     * Master send.
     * Parameters:
     * (in)     hdl         Handle returned from init()
     * (in)     buf         Buffer of data to send
     * (in)     len         Length in bytes of buf
     * (in)     stop        If !0, set stop condition when send completes
     * Returns:
     * bitmask of status bits
     */
    i2c_status_t (*send)(void *hdl, void *buf, unsigned int len,
                         unsigned int stop);
    /*
     * Master receive.
     * Parameters:
     * (in)     hdl         Handle returned from init()
     * (in)     buf         Buffer for received data
     * (in)     len         Length in bytes of buf
     * (in)     stop        If !0, set stop condition when recv completes
     * Returns:
     * bitmask of status bits
     */
    i2c_status_t (*recv)(void *hdl, void *buf, unsigned int len,
                         unsigned int stop);

    /*
     * Force the master to free the bus.
     * Returns when the stop condition has been sent.
     * Returns:
     * 0    success
     * -1   failure
     */
    int (*abort)(void *hdl, int rcvid);

    /*
     * Specify the target slave address.
     * Returns:
     * 0    success
     * -1   failure
     */
    int (*set_slave_addr)(void *hdl, unsigned int addr, i2c_addrfmt_t fmt);

    /*
     * Specify the bus speed.
     * If an invalid bus speed is requested, this function should return
     * failure and leave the bus speed unchanged.
     * Parameters:
     * (in)     speed       Bus speed. Units are implementation-defined.
     * (out)    ospeed      Actual bus speed (if NULL, this is ignored)
     * Returns:
     * 0    success
     * -1   failure
     */
    int (*set_bus_speed)(void *hdl, unsigned int speed, unsigned int *ospeed);

    /*
     * Request info about the driver.
     * Returns:
     * 0    success
     * -1   failure
     */
    int (*driver_info)(void *hdl, i2c_driver_info_t *info);

    /*
     * Handle a driver-specific devctl().
     * Parameters:
     * (in)     cmd         Device command
     * (i/o)    msg         Message buffer
     * (in)     msglen      Length of message buffer in bytes
     * (out)    nbytes      Bytes to return (<= msglen)
     * (out)    info        Extra status information returned by devctl
     * Returns:
     * EOK      success
     * errno    failure
     */
    int (*ctl)(void *hdl, int cmd, void *msg, int msglen,
               int *nbytes, int *info);

    /*
     * Reset i2c bus module.
     * Returns:
     * EOK    success
     * EIO   failure
     */
     int (*bus_reset)(void *hdl);
} i2c_master_funcs_t;

#define I2C_MASTER_GETFUNCS "i2c_master_getfuncs"

/*
 * Fills in the given table with the hardware-specific functions.
 * If a function table entry is unimplemented, it should
 * be left unchanged (and not set to NULL, etc.).
 * "funcs->size" should be set by whomever has allocated the
 * table. Don't change this.
 * Parameters:
 * (i/o)    funcs       Function table
 * (in)     tabsize     size of "funcs" in bytes
 * Returns:
 * 0    success
 * -1   failure
 */
typedef int (i2c_master_getfuncs_f)(i2c_master_funcs_t *funcs, int tabsize);
i2c_master_getfuncs_f   i2c_master_getfuncs;

#define I2C_ADD_FUNC(tabletype, table, entry, func, limit) \
    if (((size_t)&(((tabletype *)0)->entry)) + \
        sizeof (void (*)()) <= (limit)) \
        (table)->entry = (func);

#endif

#if defined(__QNXNTO__) && defined(__USESRCVERSION)
#include <sys/srcversion.h>
__SRCVERSION("$URL: http://svn.ott.qnx.com/product/branches/6.5.0/trunk/lib/i2c/public/hw/i2c.h $ $Rev: 771780 $")
#endif
