BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_customized/i2c/Makefile b/bcm68620_release/release/host_customized/i2c/Makefile
new file mode 100644
index 0000000..333c2db
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/Makefile
@@ -0,0 +1,19 @@
+# I2C devices driver
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = i2c_devs
+MOD_TYPE = linux_module
+
+srcs = bcmolt_i2c_devs.c
+
+# If called by linux kernel builder - add include paths manually.
+# It is not elegant, but we'll not have many linux modules
+ifneq ("$(KBUILD_SRC)", "")
+	-include $(OUT_DIR_BASE)/Makefile.config.$(MOD_NAME)
+endif
+
+endif
+
+USE_LINT = yes
+
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.c b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.c
new file mode 100644
index 0000000..48e9ec4
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.c
@@ -0,0 +1,1038 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h> /*copy_from_user*/
+#include <linux/proc_fs.h>
+#include "bcmos_system.h"
+#include "bcmolt_i2c_devs.h"
+#include "bcmolt_i2c_devs_ioctl.h"
+
+#define BCM_I2C_DEV_ADDR_START typedef enum {
+#define BCM_I2C_DEV_ADDR(name, desc, val) name = val,
+#define BCM_I2C_DEV_ADDR_END } bcm_i2c_dev_addr;
+
+#include "bcmolt_i2c_devs_addr.h"
+
+#define PROC_DIR_NAME       "maple_i2c"
+#define PROC_ENTRY_NAME     "i2c"
+#define MAX_EAGAIN_ITERS    200 /* 10ms per iter */
+
+/* uncomment the next line to enable debug output to the kernel CLI */
+/* #define I2C_DEBUG_PRINTS 1 */
+#ifdef I2C_DEBUG_PRINTS
+#define i2c_debug_print(fmt, args...) printk("%s#%d: " fmt, __FUNCTION__, __LINE__, ## args)
+#else
+#define i2c_debug_print(...)
+#endif
+
+int maple_i2c_chrdev_major = 216;
+module_param(maple_i2c_chrdev_major, int, S_IRUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(maple_i2c_chrdev_major, "maple_i2c_major");
+
+static struct proc_dir_entry *i2c_proc_dir;
+static struct proc_dir_entry *i2c_proc_entry;
+static char is_chrdev_reg;
+static char is_cdev_add;
+static int i2c_client_num;
+static int i2c_num_clients;
+
+const unsigned short normal_i2c[] = {
+    I2C_SW0_I2C_ADDR,
+    I2C_SW1_I2C_ADDR,
+    I2C_SW2_I2C_ADDR,
+    I2C_SW3_I2C_ADDR,
+    I2C_SW4_I2C_ADDR,
+    SFP_I2C_ADDR1,
+    SFP_I2C_ADDR2,
+    FPGA_I2C_ADDR,
+    PON_DPLL_I2C_ADDR,
+    PM_DPLL_I2C_ADDR,
+    CXP_R_I2C_ADDR,
+    PCIE_SW_I2C_ADDR,
+    I2C_CLIENT_END
+};
+
+static unsigned char slave_valid[SLAVE_NUM_OF_SLAVES] = {0};
+
+/*
+ * Driver data (common to all clients)
+ */
+
+static const struct i2c_device_id maple_i2c_id_table[] = {
+    { "maple_i2c", 0 },
+    { }
+};
+MODULE_DEVICE_TABLE(i2c, maple_i2c_id_table);
+
+static void bcm_access_fpga(void);
+
+/*
+ * Client data (each client gets its own)
+ */
+struct maple_i2c_data {
+    struct i2c_client client;
+};
+
+static struct maple_i2c_data *pclient_data_ar[SLAVE_NUM_OF_SLAVES];
+
+static int get_client(unsigned char client_num, struct i2c_client **client)
+{
+    if ((client_num >= SLAVE_NUM_OF_SLAVES) || !slave_valid[client_num])
+    {
+        i2c_debug_print("I2C error: Wrong client number 0x%x\n", client_num);
+        return -1;
+    }
+    *client = &pclient_data_ar[client_num]->client;
+
+    return 0;
+}
+
+
+/*
+ * Helper functions which attempt I2C transfer until successful, or error code is other than -EAGAIN
+ */
+
+static int maple_i2c_send(unsigned char client_num, u8 *buf, size_t count)
+{
+    struct i2c_client *client;
+    int rc;
+    int niter = 0;
+
+    if (get_client(client_num, &client))
+        return -1;
+
+    do {
+        rc = i2c_master_send(client, buf, count);
+        if (rc == -EAGAIN)
+            msleep(10);
+    } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
+    rc = (rc == count) ? 0 : (rc < 0 ) ? rc : -1;
+
+    return rc;
+}
+
+static int maple_i2c_recv(unsigned char client_num, u8 *buf, size_t count)
+{
+    struct i2c_client *client;
+    int rc;
+    int niter = 0;
+
+    if (get_client(client_num, &client))
+        return -1;
+
+    do {
+        rc = i2c_master_recv(client, buf, count);
+        if (rc == -EAGAIN)
+            msleep(10);
+    } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
+    rc = (rc == count) ? 0 : (rc < 0 ) ? rc : -1;
+
+    return rc;
+}
+
+
+static int maple_i2c_read_with_offset(unsigned char client_num, u8 *offset, size_t offset_size, u8 *buf, size_t count)
+{
+    struct i2c_client *client;
+    struct i2c_msg msg[2];
+    int rc;
+    int niter = 0;
+
+    if (get_client(client_num, &client))
+        return -1;
+
+    msg[0].addr = msg[1].addr = client->addr;
+    msg[0].flags = msg[1].flags = client->flags & I2C_M_TEN;
+
+    msg[0].len = offset_size;
+    msg[0].buf = offset;
+
+    msg[1].flags |= I2C_M_RD;
+    msg[1].len = count;
+    msg[1].buf = buf;
+
+    do {
+        rc = i2c_transfer(client->adapter, msg, 2);
+        if (rc == -EAGAIN)
+            msleep(10);
+    } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
+
+    rc = (rc == 2) ? 0 : (rc < 0 ) ? rc : -1;
+
+    return rc;
+}
+
+ssize_t maple_i2c_write(unsigned char client_num, char *buf, size_t count)
+{
+    int rc;
+
+    i2c_debug_print("Write to switch: client=0x%x val = 0x%x\n", normal_i2c[client_num], *buf);
+    rc = maple_i2c_send(client_num, (u8 *)buf, count);
+
+    if (rc < 0)
+        i2c_debug_print("Write Failed. rc=%d  client=%u[%u]\n", rc,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Successful client=%u[%u]\n",
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write);
+
+ssize_t maple_i2c_read(unsigned char client_num, char *buf, size_t count)
+{
+    int rc;
+
+    i2c_debug_print("Read from switch: client 0x%x\n", normal_i2c[client_num]);
+    rc = maple_i2c_recv(client_num, (u8 *)buf, count);
+
+    if (rc < 0)
+        i2c_debug_print("Read Failed. rc=%d  client=%u[%u]\n", rc,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Read Successful: count=%u val = 0x%x\n", (unsigned)count, *buf);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read);
+
+int maple_i2c_write_byte(unsigned char client_num, unsigned char offset, unsigned char val)
+{
+    u8 buf[2];
+    int rc;
+
+    i2c_debug_print("Write Byte: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, val);
+
+    buf[0] = offset;
+    buf[1] = val;
+    rc = maple_i2c_send(client_num, buf, 2);
+
+    if (rc < 0)
+        i2c_debug_print("Write Byte Failed. rc=%d  offset=0x%x val=0x%x client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Byte: offset=0x%x val=0x%x client=%u/%u\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_byte);
+
+int maple_i2c_read_byte(unsigned char client_num, unsigned char offset, unsigned char *data)
+{
+    u8 o = offset;
+    u8 val;
+    int rc;
+
+    i2c_debug_print("Write Byte: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, val);
+
+    rc = maple_i2c_read_with_offset(client_num, &o, 1, &val, 1);
+
+    if (rc < 0)
+        i2c_debug_print("Read Byte Failed. rc=%d  client=%u[%u]\n", rc,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = val;
+        i2c_debug_print("Read Byte: client=0x%x offset = 0x%x, val = 0x%x\n",
+            normal_i2c[client_num], offset, *data);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_byte);
+
+
+int maple_i2c_write_word(unsigned char client_num, unsigned char offset, unsigned short val)
+{
+    u8 buf[3];
+    int rc;
+
+    i2c_debug_print("Write Word: offset = 0x%x, val = 0x%x\n", offset, val);
+
+    /* The offset to be written should be the first byte in the I2C write */
+    buf[0] = offset;
+    buf[1] = (char)(val&0xFF);
+    buf[2] = (char)(val>>8);
+    rc = maple_i2c_send(client_num, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Write Word Failed. rc=%d  offset=0x%x val=0x%x, client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Word: offset=0x%x val=0x%x, client=%u[%u]\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_word);
+
+int maple_i2c_read_word(unsigned char client_num, unsigned char offset, unsigned short *data)
+{
+    u8 o = offset;
+    u8 buf[2];
+    int rc;
+
+    rc = maple_i2c_read_with_offset(client_num, &o, 1, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Read Word Failed. rc=%d  offset=0x%x client=%u[%u]\n",
+            rc, offset,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = (buf[1]<<8) | buf[0]; /* I2C data is LE */
+        i2c_debug_print("Read Word: offset = 0x%x, val = 0x%x client=%u[%u]\n",
+            offset, *data,
+            normal_i2c[client_num], client_num);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_word);
+
+
+int maple_i2c_write_reg(unsigned char client_num, unsigned char offset, int val)
+{
+    u8 buf[5];
+    int rc;
+
+    i2c_debug_print("Write Register: offset = 0x%x, val = 0x%x\n", offset, val);
+
+    /* Set the buf[0] to be the offset for write operation */
+    buf[0] = offset;
+
+    /* On the I2C bus, LS Byte should go first */
+    buf[1] = val & 0xff;
+    buf[2] = (val >> 8) & 0xff;
+    buf[3] = (val >> 16) & 0xff;
+    buf[4] = (val >> 24) & 0xff;
+    rc = maple_i2c_send(client_num, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Write Reg Failed. rc=%d offset=0x%x val=0x%x client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Reg Successful. offset=0x%x val=0x%x client=%u[%u]\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_reg);
+
+
+int maple_i2c_read_reg(unsigned char client_num, unsigned char offset, unsigned int *data)
+{
+    u8 o = offset;
+    u8 buf[4];
+    int rc;
+
+    rc = maple_i2c_read_with_offset(client_num, &o, 1, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Read Reg Failed. rc=%d offset=0x%x client=%u[%u]\n",
+            rc, offset,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); /* LS byte is transferred first */
+        i2c_debug_print("Read Register: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, *data);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_reg);
+
+
+int maple_i2c_write_fpga(unsigned char client_num, unsigned int offset, unsigned int val)
+{
+    u8 buf[8];
+    int rc;
+
+    bcm_access_fpga();
+
+    i2c_debug_print("Write fpga: offset = 0x%x, val = 0x%x\n", offset, val);
+
+    /* Set the offset for write operation */
+    //    offset = swab32(offset);
+    memcpy(&buf[0], (char*)&offset, 4);
+
+    /* On the I2C bus, LS Byte should go first */
+    //    val = swab32(val);
+    memcpy(&buf[4], (char*)&val, 4);
+
+    rc = maple_i2c_send(client_num, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Write FPGA Failed. rc=%d offset=0x%x val=0x%x client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write FPGA: offset=0x%x val=0x%x client=%u[%u]\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_fpga);
+
+int maple_i2c_read_fpga(unsigned char client_num, unsigned int offset, unsigned int *data)
+{
+    u8 obuf[4];
+    u8 buf[4];
+    int rc;
+
+    bcm_access_fpga();
+
+    /* FPGA expects 4 byte offset in BIG ENDIAN format */
+    obuf[0] = (offset >> 24) & 0xff;
+    obuf[1] = (offset >> 16) & 0xff;
+    obuf[2] = (offset >> 8) & 0xff;
+    obuf[3] = offset & 0xff;
+    rc = maple_i2c_read_with_offset(client_num, obuf, sizeof(obuf), buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Read FPGA Failed. rc=%d offset=0x%x client=%u[%u]\n",
+            rc, offset,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24); /* MS byte is transferred first */
+        i2c_debug_print("Read FPGA: offset = 0x%x, val = 0x%x %02x %02x %02x %02x  client=%u[%u]\n",
+            offset, *data, buf[0], buf[1], buf[2], buf[3],
+            normal_i2c[client_num], client_num);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_fpga);
+
+enum client_num maple_i2c_get_client(u32 addr)
+{
+    enum client_num i = 0;
+    while (i < SLAVE_NUM_OF_SLAVES)
+    {
+        if (pclient_data_ar[i])
+        {
+            if (slave_valid[i] && pclient_data_ar[i]->client.addr == addr)
+            {
+                break;
+            }
+        }
+        i++;
+    }
+    return i;
+}
+EXPORT_SYMBOL(maple_i2c_get_client);
+
+static int dev_change(u32 addr)
+{
+    enum client_num i = maple_i2c_get_client(addr);
+
+    if (i < SLAVE_NUM_OF_SLAVES)
+    {
+        i2c_client_num = i;
+        i2c_debug_print("Slave was set successfully i %d, addr 0x%x\n", i, addr);
+    }
+    else
+    {
+        i2c_debug_print("Failed to set slave i %d, addr 0x%x\n", i, addr);
+    }
+
+    return 0;
+}
+
+static void bcm_access_fpga(void)
+{
+    static int access_enabled;
+    int fpga_client_num  = maple_i2c_get_client(I2C_SW1_I2C_ADDR);
+    uint8_t  b;
+
+    if (access_enabled)
+    	return;
+    b = 4;
+    maple_i2c_write(fpga_client_num, &b, 1);
+    access_enabled = 1;
+}
+#define BCM_FPGA_REG_RESETS 0x2
+#define BCM_FPGA_REG_FPGA_VERSION 0x0
+/* 1 = out of reset bcm_board_config_reset_value */
+void reset_maple(int bit,int param)
+{
+    int fpga_client_num  = maple_i2c_get_client(FPGA_I2C_ADDR);
+    int sw_client_num  = maple_i2c_get_client(I2C_SW0_I2C_ADDR);
+    uint8_t  b = 1;
+    uint32_t reset_values;
+
+    maple_i2c_write(sw_client_num, &b, 1);
+
+    /* Read-modify-write so we can set only the relevant bit */
+    maple_i2c_read_fpga(fpga_client_num, BCM_FPGA_REG_RESETS, &reset_values);
+
+    if (param)
+        reset_values |= 1 << bit;
+    else
+        reset_values &= ~(1 << bit);
+    maple_i2c_write_fpga(fpga_client_num, BCM_FPGA_REG_RESETS, reset_values);
+}
+EXPORT_SYMBOL(reset_maple);
+
+/* Calls the appropriate function based on user command */
+static int exec_command(const char *buf, size_t count)
+{
+#define MAX_ARGS 4
+#define MAX_ARG_SIZE 32
+    int i, argc = 0, val = 0;
+    char cmd;
+    u32 offset = 0;
+    char arg[MAX_ARGS][MAX_ARG_SIZE];
+#define LOG_WR_KBUF_SIZE 128
+    char kbuf[LOG_WR_KBUF_SIZE];
+
+    if ((count > LOG_WR_KBUF_SIZE-1) || (copy_from_user(kbuf, buf, count) != 0))
+        return -EFAULT;
+    kbuf[count]=0;
+    argc = sscanf(kbuf, "%c %s %s %s %s", &cmd, arg[0], arg[1], arg[2], arg[3]);
+
+    if (argc < 1)
+    {
+        printk("Need at-least 2 arguments\n");
+        return -EFAULT;
+    }
+
+    for (i=0; i<MAX_ARGS; ++i) {
+        arg[i][MAX_ARG_SIZE-1] = '\0';
+    }
+    offset = (u32)simple_strtoul(arg[0], NULL, 0);
+    if (argc == 3)
+        val = (int)simple_strtoul(arg[1], NULL, 0);
+
+    switch (cmd)
+    {
+    case 'm':
+        reset_maple(0,offset); // maple out of reset(1) | reset (0)
+        break;
+    case 'k':
+        reset_maple(4,offset); // katana2 out of reset(1) | reset (0)
+        break;
+    case 'b':
+        if (argc == 3)
+            maple_i2c_write_byte(i2c_client_num, (u8)offset, (u8)val);
+        else
+        {
+            u8 data;
+            maple_i2c_read_byte(i2c_client_num, (u8)offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 's':
+        if (argc == 2)
+        {
+            u8 data = (u8)offset;
+            maple_i2c_write(i2c_client_num, &data, 1);
+        }
+        else
+        {
+            u8 data = offset;
+            maple_i2c_read(i2c_client_num, &data, 1);
+            printk("client 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], data);
+        }
+        break;
+
+    case 'w':
+        if (argc == 3)
+            maple_i2c_write_word(i2c_client_num, (u8)offset, (u16)val);
+        else
+        {
+            u16 data;
+            maple_i2c_read_word(i2c_client_num, (u8)offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 'd':
+        if (argc == 3)
+            maple_i2c_write_reg(i2c_client_num, (u8)offset, val);
+        else
+        {
+            u32 data;
+            maple_i2c_read_reg(i2c_client_num, (u8)offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 'f':
+        if (argc == 3)
+            maple_i2c_write_fpga(i2c_client_num, offset, val);
+        else
+        {
+            u32 data;
+            maple_i2c_read_fpga(i2c_client_num, offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 'c':
+        dev_change(offset);
+        break;
+
+    default:
+        printk("Invalid command.\n Valid commands:\n"
+            "  Change I2C Addr: c addr\n"
+            "  Write Reg:       d offset val\n"
+            "  Read Reg:        d offset\n"
+            "  Write Word:      w offset val\n"
+            "  Read Word:       w offset\n"
+            "  Write Byte:      b offset val\n"
+            "  Read Byte:       b offset\n"
+            "  Write fpga:      f offset val\n"
+            "  Read fpga:       f offset\n"
+            "  Write to switch: s val (one byte)\n"
+            "  Read from switch:s\n"
+            "  Maple:           m <0|1>\n"
+            "  Katana2:         k <0|1>\n"
+            );
+        break;
+    }
+    return count;
+}
+
+
+
+/* Read Function of PROCFS attribute "maple_i2c/test" */
+static ssize_t maple_i2c_proc_test_read(struct file *f, char *buf, size_t count,
+    loff_t *pos)
+{
+    printk(" Usage: echo command > "
+        " /proc/maple_i2c/test\n");
+    printk(" supported commands:\n"
+        "  Change I2C Addr: c addr\n"
+        "  Write Reg:       d offset val\n"
+        "  Read Reg:        d offset\n"
+        "  Write Word:      w offset val\n"
+        "  Read Word:       w offset\n"
+        "  Write Byte:      b offset val\n"
+        "  Read Byte:       b offset\n"
+        "  Write fpga:      f offset val\n"
+        "  Read fpga:       f offset\n"
+        "  Write to switch: s val (one byte)\n"
+        "  Read from switch:s\n"
+        );
+    return 0;
+}
+
+/* Write Function of PROCFS attribute "maple_i2c/test" */
+static ssize_t maple_i2c_proc_test_write(struct file *f, const char *buf,
+    size_t count, loff_t *pos)
+{
+    return exec_command(buf, count);
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int maple_i2c_dev_detect(struct i2c_client *client, struct i2c_board_info *info)
+{
+    i2c_debug_print("detecting i2c device 0x%x\n", client->addr);
+
+    /* TODO: detection and identification */
+
+    strcpy(info->type, "maple_i2c");
+    info->flags = 0;
+    return 0;
+}
+
+static struct file_operations maple_i2c_fops =
+{
+    read: maple_i2c_proc_test_read,
+    write: maple_i2c_proc_test_write
+};
+
+static int maple_i2c_dev_create_proc(void)
+{
+    i2c_proc_dir = proc_mkdir(PROC_DIR_NAME, NULL);
+    if (!i2c_proc_dir)
+    {
+        i2c_debug_print("fail to create proc dir\n");
+        return -ENOMEM;
+    }
+
+    i2c_proc_entry = create_proc_entry(PROC_ENTRY_NAME, 0, i2c_proc_dir);
+    if (!i2c_proc_entry)
+    {
+        remove_proc_entry(PROC_DIR_NAME, NULL);
+        return -ENOMEM;
+    }
+
+    i2c_proc_entry->proc_fops = &maple_i2c_fops;
+
+    return 0;
+}
+
+static int maple_i2c_chrdev_open(struct inode *inode, struct file *filp)
+{
+    return 0;
+}
+
+static int maple_i2c_chrdev_release(struct inode *inode, struct file *filp)
+{
+    return 0;
+}
+
+static long maple_i2c_chrdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    int linux_rc = 0;
+    int rc;
+    maple_i2c_ioctl_param params;
+
+    /* don't even decode wrong cmds: better returning  ENOTTY than EFAULT */
+    if (_IOC_TYPE(cmd) != MAPLE_I2C_IOCTL_MAGIC)
+        return -ENOTTY;
+
+    /*
+     * the type is a bitmask, and VERIFY_WRITE catches R/W
+     * transfers. Note that the type is user-oriented, while
+     * verify_area is kernel-oriented, so the concept of "read" and
+     * "write" is reversed
+     */
+    if (_IOC_DIR(cmd) & _IOC_READ)
+        linux_rc = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+    else if (_IOC_DIR(cmd) & _IOC_WRITE)
+        linux_rc =  !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+    if (linux_rc)
+        return -EFAULT;
+
+    switch (cmd)
+    {
+    case MAPLE_I2C_IOCTL_OP_DEV_CHANGE:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            return dev_change(params.addr);
+        }
+        break;
+    case MAPLE_I2C_IOCTL_OP_DEV_WRITE:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            switch (params.count)
+            {
+            case 8:
+                return maple_i2c_write_byte(i2c_client_num, params.addr, params.val);
+            case 16:
+                return maple_i2c_write_word(i2c_client_num, params.addr, params.val);
+            case 32:
+                return maple_i2c_write_reg(i2c_client_num, params.addr, params.val);
+            default:
+                return -EINVAL;
+            }
+        }
+        break;
+    case MAPLE_I2C_IOCTL_OP_DEV_READ:
+        {
+            unsigned char b;
+            unsigned short w;
+            unsigned int r;
+
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            switch (params.count)
+            {
+            case 8:
+                linux_rc = maple_i2c_read_byte(i2c_client_num, params.addr, &b);
+                if (linux_rc < 0)
+                    break;
+                params.val = b;
+                break;
+            case 16:
+                linux_rc = maple_i2c_read_word(i2c_client_num, params.addr, &w);
+                if (linux_rc < 0)
+                    break;
+                params.val = w;
+                break;
+            case 32:
+                linux_rc = maple_i2c_read_reg(i2c_client_num, params.addr, &r);
+                if (linux_rc < 0)
+                    break;
+                params.val = r;
+                break;
+            default:
+                return -EINVAL;
+            }
+            if (linux_rc < 0)
+                break;
+            return copy_to_user((char *)arg, (char *)&params, sizeof(params));
+        }
+    case MAPLE_I2C_IOCTL_OP_SWITCH_WRITE:
+        {
+            char b;
+
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            b = params.val;
+            return maple_i2c_write(i2c_client_num, &b, 1);
+        }
+    case MAPLE_I2C_IOCTL_OP_SWITCH_READ:
+        {
+            char b;
+
+            linux_rc = maple_i2c_read(i2c_client_num, &b, 1);
+            if (linux_rc < 0)
+                break;
+            params.val = b;
+            return copy_to_user((char *)arg, (char *)&params, sizeof(params));
+        }
+    case MAPLE_I2C_IOCTL_OP_FPGA_WRITE:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            return maple_i2c_write_fpga(i2c_client_num, params.addr, params.val);
+        }
+    case MAPLE_I2C_IOCTL_OP_FPGA_READ:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            linux_rc = maple_i2c_read_fpga(i2c_client_num, params.addr, &params.val);
+            if (linux_rc < 0)
+                break;
+            return copy_to_user((char *)arg, (char *)&params, sizeof(params));
+        }
+    default:
+        rc = -ENOTTY;
+        break;
+    }
+
+    return linux_rc;
+}
+
+static ssize_t maple_i2c_chrdev_write(struct file *filp, const char __user *buf,
+    size_t count, loff_t *f_pos)
+{
+    return 0;
+}
+
+static struct file_operations maple_i2c_chrdev_fops =
+{
+    .owner = THIS_MODULE,
+    .open = maple_i2c_chrdev_open,
+    .release = maple_i2c_chrdev_release,
+    .write = maple_i2c_chrdev_write,
+    .unlocked_ioctl = maple_i2c_chrdev_ioctl
+};
+
+static struct cdev maple_i2c_chrdev_cdev;
+
+static int maple_i2c_dev_create_chrdev(void)
+{
+    dev_t dev = MKDEV(maple_i2c_chrdev_major, 0);
+    int linux_rc;
+
+    is_chrdev_reg = 0;
+    is_cdev_add = 0;
+    /*
+     * Register your major, and accept a dynamic number.
+     */
+    if (!maple_i2c_chrdev_major)
+        return -1;
+    linux_rc = register_chrdev_region(dev, 0, "maple_i2c");
+    if (linux_rc < 0)
+    {
+        i2c_debug_print("register_chrdev_region()->%d\n", linux_rc);
+        return -EIO;
+    }
+    is_chrdev_reg = 1;
+
+    cdev_init(&maple_i2c_chrdev_cdev, &maple_i2c_chrdev_fops);
+    linux_rc = cdev_add(&maple_i2c_chrdev_cdev, dev, 1);
+    if (linux_rc < 0)
+    {
+        i2c_debug_print("cdev_add()->%d\n", linux_rc);
+        return -EIO;
+    }
+    is_cdev_add = 1;
+
+    return 0;
+}
+
+static int maple_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+    int err = 0;
+    struct maple_i2c_data *pclient_data;
+
+    i2c_debug_print("!!!! i2c device 0x%x probe\n", client->addr);
+
+    if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+        goto exit;
+
+    if (!(pclient_data = kzalloc(sizeof(struct maple_i2c_data), GFP_KERNEL)))
+    {
+        err = -ENOMEM;
+        goto exit;
+    }
+
+    pclient_data->client.addr = client->addr;
+    pclient_data->client.adapter = client->adapter;
+    pclient_data->client.driver = client->driver;
+    pclient_data->client.flags = client->flags;
+
+    i2c_set_clientdata(client, pclient_data);
+
+    switch(client->addr)
+    {
+    case I2C_SW0_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_70] = pclient_data;
+        slave_valid[SLAVE_SWITCH_70] = 1;
+        break;
+    case I2C_SW1_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_71] = pclient_data;
+        slave_valid[SLAVE_SWITCH_71] = 1;
+        break;
+    case I2C_SW2_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_72] = pclient_data;
+        slave_valid[SLAVE_SWITCH_72] = 1;
+        break;
+    case I2C_SW3_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_73] = pclient_data;
+        slave_valid[SLAVE_SWITCH_73] = 1;
+        break;
+    case I2C_SW4_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_74] = pclient_data;
+        slave_valid[SLAVE_SWITCH_74] = 1;
+        break;
+    case SFP_I2C_ADDR1:
+        pclient_data_ar[SLAVE_SFP_50] = pclient_data;
+        slave_valid[SLAVE_SFP_50] = 1;
+        break;
+    case SFP_I2C_ADDR2:
+        pclient_data_ar[SLAVE_SFP_51] = pclient_data;
+        slave_valid[SLAVE_SFP_51] = 1;
+        break;
+    case FPGA_I2C_ADDR:
+        pclient_data_ar[SLAVE_FPGA_40] = pclient_data;
+        slave_valid[SLAVE_FPGA_40] = 1;
+        break;
+    case PON_DPLL_I2C_ADDR:
+        pclient_data_ar[SLAVE_PON_DPLL_68] = pclient_data;
+        slave_valid[SLAVE_PON_DPLL_68] = 1;
+        break;
+    case PM_DPLL_I2C_ADDR:
+        pclient_data_ar[SLAVE_PM_DPLL_6A] = pclient_data;
+        slave_valid[SLAVE_PM_DPLL_6A] = 1;
+        break;
+    case CXP_R_I2C_ADDR:
+        pclient_data_ar[SLAVE_CXP_R_54] = pclient_data;
+        slave_valid[SLAVE_CXP_R_54] = 1;
+        break;
+    case PCIE_SW_I2C_ADDR:
+        pclient_data_ar[SLAVE_PCIE_SW_3C] = pclient_data;
+        slave_valid[SLAVE_PCIE_SW_3C] = 1;
+        break;
+    default:
+        i2c_debug_print("%s client addr out of range 0x%x\n", __FUNCTION__, client->addr);
+        goto exit_kfree;
+    }
+
+    /* Create only once */
+    if (i2c_proc_entry == NULL)
+    {
+        if (maple_i2c_dev_create_proc() < 0)
+            goto exit_kfree;
+    }
+    if (!is_cdev_add)
+    {
+        if (maple_i2c_dev_create_chrdev() < 0)
+            goto exit_kfree;
+    }
+    ++i2c_num_clients;
+
+    return 0;
+
+exit_kfree:
+    kfree(pclient_data);
+exit:
+    return err;
+}
+
+static int maple_i2c_dev_remove(struct i2c_client *client)
+{
+    kfree(i2c_get_clientdata(client));
+    --i2c_num_clients;
+    if (!i2c_num_clients)
+    {
+        if (i2c_proc_entry != NULL)
+        {
+            remove_proc_entry(PROC_ENTRY_NAME, i2c_proc_dir);
+            i2c_proc_entry = NULL;
+        }
+        if (i2c_proc_dir != NULL)
+        {
+            remove_proc_entry(PROC_DIR_NAME, NULL);
+            i2c_proc_dir = NULL;
+        }
+        if (is_cdev_add)
+        {
+            cdev_del(&maple_i2c_chrdev_cdev);
+            is_cdev_add = 0;
+        }
+        if (is_chrdev_reg)
+        {
+            unregister_chrdev_region(MKDEV(maple_i2c_chrdev_major, 0), 1);
+            is_chrdev_reg = 0;
+        }
+    }
+
+    return 0;
+}
+
+static struct i2c_driver maple_i2c_dev_driver = {
+    .class		= ~0,
+    .driver = {
+        .name	= "maple_i2c",
+    },
+    .probe		= maple_i2c_dev_probe,
+    .remove		= maple_i2c_dev_remove,
+    .id_table	= maple_i2c_id_table,
+    .detect		= maple_i2c_dev_detect,
+    .address_list	= normal_i2c,
+};
+
+module_i2c_driver(maple_i2c_dev_driver);
+
+MODULE_DESCRIPTION("maple i2c devices");
+MODULE_LICENSE("GPL");
+
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.h b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.h
new file mode 100644
index 0000000..ad0edaa
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.h
@@ -0,0 +1,226 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifndef _BCMOLT_I2C_DEVS_H_
+#define _BCMOLT_I2C_DEVS_H_
+
+/* When inserting the module (with insmod) onlt the I2C switch devices (I2C_SWX_I2C_ADDR) 
+   will be automatically detected, and therefore will be probed.
+   Probing all other devices can be done after inerting the module via sysfs.
+   for example, in order to probe FPGA device, the following line should be applied:
+   -- echo maple_i2c FPGA_I2C_ADDR > /sys/bus/i2c/devices/i2c-0/new_device --
+*/ 
+enum client_num
+{
+    SLAVE_SWITCH_70    = 0,
+    SLAVE_SWITCH_71    = 1,
+    SLAVE_SWITCH_72    = 2,
+    SLAVE_SWITCH_73    = 3,
+    SLAVE_SWITCH_74    = 4,
+    SLAVE_SFP_50       = 5,
+    SLAVE_SFP_51       = 6,
+    SLAVE_FPGA_40      = 7,
+    SLAVE_PON_DPLL_68  = 8,
+    SLAVE_PM_DPLL_6A   = 9,
+    SLAVE_CXP_R_54     = 10,
+    SLAVE_PCIE_SW_3C   = 11,
+    SLAVE_NUM_OF_SLAVES
+};
+
+
+/*****************************************************************
+   maple_i2c_write
+
+   DESCRIPTION:
+       Writes serially data to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       buf        - The buffer to write.
+       count      - Number of bytes to write
+
+   OUTPUT:
+       The number of bytes that were written, when fails return negative number
+********************************************************************/
+ssize_t maple_i2c_write(unsigned char client_num, char *buf, size_t count);
+
+/*****************************************************************
+   maple_i2c_read
+
+   DESCRIPTION:
+       Read serially data from I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       buf        - The buffer to read to.
+       count      - Number of bytes to read
+
+   OUTPUT:
+       The number of bytes that were read, when fails return negative number
+********************************************************************/
+ssize_t maple_i2c_read(unsigned char client_num, char *buf, size_t count);
+
+/*****************************************************************
+   maple_i2c_write_byte
+
+   DESCRIPTION:
+       Write byte to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_byte(unsigned char client_num, unsigned char offset, unsigned char val);
+
+/*****************************************************************
+   maple_i2c_read_byte
+
+   DESCRIPTION:
+       Read byte from I2C device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_byte(unsigned char client_num, unsigned char offset, unsigned char* data);
+
+/*****************************************************************
+   maple_i2c_write_word
+
+   DESCRIPTION:
+       Write 16 bit word to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_word(unsigned char client_num, unsigned char offset, unsigned short val);
+
+/*****************************************************************
+   maple_i2c_read_word
+
+   DESCRIPTION:
+       Read 16 bit word from I2C device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_word(unsigned char client_num, unsigned char offset, unsigned short* data);
+
+/*****************************************************************
+   maple_i2c_write_reg
+
+   DESCRIPTION:
+       Write 32 bit register to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_reg(unsigned char client_num, unsigned char offset, int val);
+
+/*****************************************************************
+   maple_i2c_read_reg
+
+   DESCRIPTION:
+       Read 32 bit word from I2C device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_reg(unsigned char client_num, unsigned char offset, unsigned int* data);
+
+/*****************************************************************
+   maple_i2c_write_fpga
+
+   DESCRIPTION:
+       Write 32 bit register to I2C fpga device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_fpga(unsigned char client_num, unsigned int offset, unsigned int val);
+
+/*****************************************************************
+   maple_i2c_read_fpga
+
+   DESCRIPTION:
+       Read 32 bit word from I2C fpga device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_fpga(unsigned char client_num, unsigned int offset, unsigned int* data);
+
+/*****************************************************************
+   maple_i2c_get_client
+
+   DESCRIPTION:
+       Gets an I2C client number from an address
+
+   PARAMETERS:
+       addr       - The address of the client.
+   OUTPUT:
+       The client number for this client, or SLAVE_NUM_OF_SLAVES on failure.
+********************************************************************/
+enum client_num maple_i2c_get_client(unsigned int addr);
+
+#endif   /* _MAPLE_I2C_DEVS_H_ */
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_addr.h b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_addr.h
new file mode 100644
index 0000000..f1a9a2c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_addr.h
@@ -0,0 +1,50 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifndef _BCMOLT_I2C_DEVS_ADDR_H_
+#define _BCMOLT_I2C_DEVS_ADDR_H_
+
+BCM_I2C_DEV_ADDR_START
+BCM_I2C_DEV_ADDR(I2C_SW0_I2C_ADDR, "sw0", 0x70)
+BCM_I2C_DEV_ADDR(I2C_SW1_I2C_ADDR, "sw1", 0x71)
+BCM_I2C_DEV_ADDR(I2C_SW2_I2C_ADDR, "sw2", 0x72)
+BCM_I2C_DEV_ADDR(I2C_SW3_I2C_ADDR, "sw3", 0x73)
+BCM_I2C_DEV_ADDR(I2C_SW4_I2C_ADDR, "sw4", 0x74)
+BCM_I2C_DEV_ADDR(SFP_I2C_ADDR1, "sfp1", 0x50)
+BCM_I2C_DEV_ADDR(SFP_I2C_ADDR2, "sfp2", 0x51)
+BCM_I2C_DEV_ADDR(FPGA_I2C_ADDR, "fpga", 0x40)
+BCM_I2C_DEV_ADDR(PON_DPLL_I2C_ADDR, "pon_dpll", 0x68)
+BCM_I2C_DEV_ADDR(PM_DPLL_I2C_ADDR, "pm_dpll", 0x6a)
+BCM_I2C_DEV_ADDR(CXP_T_I2C_ADDR, "cxp_t", 0x50)
+BCM_I2C_DEV_ADDR(CXP_R_I2C_ADDR, "cxp_r", 0x54)
+BCM_I2C_DEV_ADDR(PCIE_SW_I2C_ADDR, "pcie_sw", 0x3c)
+BCM_I2C_DEV_ADDR_END
+
+#endif
+
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_ioctl.h b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_ioctl.h
new file mode 100644
index 0000000..e15f71a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_ioctl.h
@@ -0,0 +1,24 @@
+#ifndef _BCMOLT_I2C_DEVS_IOCTL_H_
+#define _BCMOLT_I2C_DEVS_IOCTL_H_
+
+#include <linux/ioctl.h>
+
+typedef struct
+{
+    uint32_t count;
+    uint32_t addr;
+    uint32_t val;
+} maple_i2c_ioctl_param;
+
+#define MAPLE_I2C_IOCTL_MAGIC 'I'
+
+#define MAPLE_I2C_IOCTL_OP_DEV_CHANGE _IOW(MAPLE_I2C_IOCTL_MAGIC, 1, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_DEV_WRITE _IOW(MAPLE_I2C_IOCTL_MAGIC, 2, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_DEV_READ _IOWR(MAPLE_I2C_IOCTL_MAGIC, 3, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_SWITCH_WRITE _IOW(MAPLE_I2C_IOCTL_MAGIC, 4, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_SWITCH_READ _IOR(MAPLE_I2C_IOCTL_MAGIC, 5, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_FPGA_WRITE _IOW(MAPLE_I2C_IOCTL_MAGIC, 6, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_FPGA_READ _IOWR(MAPLE_I2C_IOCTL_MAGIC, 7, maple_i2c_ioctl_param)
+
+#endif
+