#ifndef SONY_FPGA_LOCAL_IF_I2C_H
#define SONY_FPGA_LOCAL_IF_I2C_H

#include <linux/types.h>

// I2Cドライバレジスタマップ
#define FPGA_OFFSET_I2C_CMD     0x10
#define FPGA_OFFSET_I2C_PRSCL   0x14
#define FPGA_OFFSET_I2C_TX      0x20
#define FPGA_OFFSET_I2C_STS     0x38
#define FPGA_OFFSET_I2C_RX      0x3C

// I2Cコマンド
#define FPGA_VAL_I2C_CMD_TXPURGE    0x0008
#define FPGA_VAL_I2C_CMD_RXPURGE    0x0004
#define FPGA_VAL_I2C_CMD_PURGE \
    (FPGA_VAL_I2C_CMD_TXPURGE | \
     FPGA_VAL_I2C_CMD_RXPURGE)
#define FPGA_VAL_I2C_CMD_CORERST    0x0002
#define FPGA_VAL_I2C_CMD_COREEN     0x0001

// I2Cステータス
#define FPGA_VAL_I2C_STS_BUSY       0x0800
#define FPGA_VAL_I2C_STS_AL         0x0400
#define FPGA_VAL_I2C_STS_RXACK      0x0200
#define FPGA_VAL_I2C_STS_RDWR       0x0100
#define FPGA_VAL_I2C_STS_TXFULL     0x0010
#define FPGA_VAL_I2C_STS_TXEMPTY    0x0008
#define FPGA_VAL_I2C_STS_RXFULL     0x0004
#define FPGA_VAL_I2C_STS_RXHIGH     0x0002
#define FPGA_VAL_I2C_STS_RXEXIST    0x0001

#define FPGA_VAL_I2C_TX_CMD_START   0x0800
#define FPGA_VAL_I2C_TX_CMD_STOP    0x0400
#define FPGA_VAL_I2C_TX_CMD_READ    0x0200
#define FPGA_VAL_I2C_TX_CMD_WRITE   0x0100

#define I2C_PAGE_SIZE   32
#define I2C_RETRY_COUNT 200000
#define I2C_SYS_FREQ    (100*1000*1000) // 100MHz

#define I2C_PR_ERR(info, x, ...) \
    pr_err("I2C 0x%08llx: " x ", status=%x\n", \
          (u64 __force)info, ##__VA_ARGS__, i2c_get_status(info))

#define QSFP_SUPPORT_VENDOR_FINISAR "FINISAR "
#define QSFP_SUPPORT_VENDOR_CIG "CIG "

struct i2c_dev_info {
    u32 slave_addr;
    u32 addr_size;
};

struct i2c_settings {
    u32 pci_address;
    u32 slave_address;
    u32 i2c_address;
    u32 setting;
    u32 mask;
};

extern void i2c_driver_init(void __iomem* base_addr);
extern int i2c_tx(void __iomem* base_addr, const struct i2c_dev_info* dev_info, u32 addr, const u8* data, u32 length);
extern int i2c_rx(void __iomem* base_addr, const struct i2c_dev_info* dev_info, u32 addr, u8* data, u32 length);
extern int module_param_qsfp_poll_spare_time;
#endif
