diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini
new file mode 100755
index 000000000000..ba13dd5743bc
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini
@@ -0,0 +1,57 @@
+# name          lanes             alias	        index
+Ethernet0       1                 Ethernet0     0
+Ethernet1       2                 Ethernet1     1
+Ethernet2       3                 Ethernet2     2
+Ethernet3       4                 Ethernet3     3
+Ethernet4       5                 Ethernet4     4
+Ethernet5       6                 Ethernet5     5
+Ethernet6       7                 Ethernet6     6
+Ethernet7       8                 Ethernet7     7
+Ethernet8       13                Ethernet8     8
+Ethernet9       14                Ethernet9     9
+Ethernet10      15                Ethernet10    10
+Ethernet11      16                Ethernet11    11
+Ethernet12      21                Ethernet12    12
+Ethernet13      22                Ethernet13    13
+Ethernet14      23                Ethernet14    14
+Ethernet15      24                Ethernet15    15
+Ethernet16      29                Ethernet16    16
+Ethernet17      30                Ethernet17    17
+Ethernet18      31                Ethernet18    18
+Ethernet19      32                Ethernet19    19
+Ethernet20      33                Ethernet20    20
+Ethernet21      34                Ethernet21    21
+Ethernet22      35                Ethernet22    22
+Ethernet23      36                Ethernet23    23
+Ethernet24      41                Ethernet24    24
+Ethernet25      42                Ethernet25    25
+Ethernet26      43                Ethernet26    26
+Ethernet27      44                Ethernet27    27
+Ethernet28      49                Ethernet28    28
+Ethernet29      50                Ethernet29    29
+Ethernet30      51                Ethernet30    30
+Ethernet31      52                Ethernet31    31
+Ethernet32      57                Ethernet32    32
+Ethernet33      58                Ethernet33    33
+Ethernet34      59                Ethernet34    34
+Ethernet35      60                Ethernet35    35
+Ethernet36      61                Ethernet36    36
+Ethernet37      62                Ethernet37    37
+Ethernet38      63                Ethernet38    38
+Ethernet39      64                Ethernet39    39
+Ethernet40      65                Ethernet40    40
+Ethernet41      66                Ethernet41    41
+Ethernet42      67                Ethernet42    42
+Ethernet43      68                Ethernet43    43
+Ethernet44      69                Ethernet44    44
+Ethernet45      70                Ethernet45    45
+Ethernet46      71                Ethernet46    46
+Ethernet47      72                Ethernet47    47
+Ethernet48      85,86,87,88       Ethernet48    48
+Ethernet52      77,78,79,80       Ethernet52    49
+Ethernet56      93,94,95,96       Ethernet56    50
+Ethernet60      97,98,99,100      Ethernet60    51
+Ethernet64      113,114,115,116   Ethernet64    52
+Ethernet68      105,106,107,108   Ethernet68    53
+Ethernet72      121,122,123,124   Ethernet72    54
+Ethernet76      125,126,127,128   Ethernet76    55
diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/sai.profile b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/sai.profile
new file mode 100755
index 000000000000..f147d44c0b34
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/sai.profile
@@ -0,0 +1,2 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6356-48x25G-8x100G.config.bcm
+SAI_NUM_ECMP_MEMBERS=32
diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm
new file mode 100644
index 000000000000..f6fc4f02f1ef
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm
@@ -0,0 +1,398 @@
+### fix for sonic
+ptp_ts_pll_fref=50000000
+ptp_bs_fref_0=50000000
+ptp_bs_fref_1=50000000
+### end fix
+
+
+core_clock_frequency=1525
+dpp_clock_ratio=2:3
+
+oversubscribe_mode=1
+pbmp_xport_xe=0x488787878808787fdfe1e1e1fe1e1e1fe
+
+
+portmap_65=130:10
+
+### Pipeline0, halfpipe 0 (12x25G + 2x100G)
+portmap_1=1:25
+portmap_2=2:25
+portmap_3=3:25
+portmap_4=4:25
+portmap_5=5:25
+portmap_6=6:25
+portmap_7=7:25
+portmap_8=8:25
+portmap_13=13:25
+portmap_14=14:25
+portmap_15=15:25
+portmap_16=16:25
+portmap_21=21:25
+portmap_22=22:25
+portmap_23=23:25
+portmap_24=24:25
+portmap_29=29:25
+portmap_30=30:25
+portmap_31=31:25
+portmap_32=32:25
+
+### Pipeline0, halfpipe 1 (12x25G + 2x100G)
+portmap_33=33:25
+portmap_34=34:25
+portmap_35=35:25
+portmap_36=36:25
+portmap_41=41:25
+portmap_42=42:25
+portmap_43=43:25
+portmap_44=44:25
+portmap_49=49:25
+portmap_50=50:25
+portmap_51=51:25
+portmap_52=52:25
+portmap_57=57:25
+portmap_58=58:25
+portmap_59=59:25
+portmap_60=60:25
+portmap_61=61:25
+portmap_62=62:25
+portmap_63=63:25
+portmap_64=64:25
+
+### Pipeline 1
+### First management port
+portmap_66=129:10:m
+### Second management port
+portmap_130=128:10:m
+### Loopback port
+portmap_131=131:10
+
+### Pipeline 1, halfpipe 0 (12x25G + 2x100G)
+portmap_67=65:25
+portmap_68=66:25
+portmap_69=67:25
+portmap_70=68:25
+portmap_71=69:25
+portmap_72=70:25
+portmap_73=71:25
+portmap_74=72:25
+portmap_79=77:100
+portmap_87=85:100
+portmap_95=93:100
+
+### Pipeline 1, halfpipe 1 (12x25G + 2x100G)
+portmap_99=97:100
+portmap_107=105:100
+portmap_115=113:100
+portmap_123=121:100
+portmap_127=125:100
+
+l2_mem_entries=32768
+l3_mem_entries=16384
+fpem_mem_entries=16384
+l2xmsg_mode=1
+
+
+#dport part
+dport_map_port_79=87
+dport_map_port_87=79
+dport_map_port_107=115
+dport_map_port_115=107
+
+#Polarity flips after lane swaps
+#rx part
+#FC1
+phy_chain_rx_polarity_flip_physical{5.0}=0x1
+phy_chain_rx_polarity_flip_physical{6.0}=0x1
+phy_chain_rx_polarity_flip_physical{7.0}=0x1
+phy_chain_rx_polarity_flip_physical{8.0}=0x1
+
+#FC3
+phy_chain_rx_polarity_flip_physical{13.0}=0x1
+phy_chain_rx_polarity_flip_physical{14.0}=0x1
+phy_chain_rx_polarity_flip_physical{15.0}=0x1
+phy_chain_rx_polarity_flip_physical{16.0}=0x1
+
+#FC5
+phy_chain_rx_polarity_flip_physical{21.0}=0x1
+phy_chain_rx_polarity_flip_physical{22.0}=0x1
+phy_chain_rx_polarity_flip_physical{23.0}=0x1
+phy_chain_rx_polarity_flip_physical{24.0}=0x1
+
+#FC8
+phy_chain_rx_polarity_flip_physical{33.0}=0x1
+phy_chain_rx_polarity_flip_physical{34.0}=0x1
+phy_chain_rx_polarity_flip_physical{35.0}=0x1
+phy_chain_rx_polarity_flip_physical{36.0}=0x1
+
+#FC10
+phy_chain_rx_polarity_flip_physical{41.0}=0x1
+phy_chain_rx_polarity_flip_physical{42.0}=0x1
+phy_chain_rx_polarity_flip_physical{43.0}=0x1
+phy_chain_rx_polarity_flip_physical{44.0}=0x1
+
+#FC12
+phy_chain_rx_polarity_flip_physical{49.0}=0x1
+phy_chain_rx_polarity_flip_physical{50.0}=0x1
+phy_chain_rx_polarity_flip_physical{51.0}=0x1
+phy_chain_rx_polarity_flip_physical{52.0}=0x1
+
+#FC14
+phy_chain_rx_polarity_flip_physical{57.0}=0x1
+phy_chain_rx_polarity_flip_physical{58.0}=0x1
+phy_chain_rx_polarity_flip_physical{59.0}=0x1
+phy_chain_rx_polarity_flip_physical{60.0}=0x1
+
+#FC15
+phy_chain_rx_polarity_flip_physical{63.0}=0x1
+phy_chain_rx_polarity_flip_physical{64.0}=0x1
+
+#FC16
+phy_chain_rx_polarity_flip_physical{65.0}=0x1
+phy_chain_rx_polarity_flip_physical{66.0}=0x1
+
+#FC17
+phy_chain_rx_polarity_flip_physical{69.0}=0x1
+phy_chain_rx_polarity_flip_physical{70.0}=0x1
+phy_chain_rx_polarity_flip_physical{71.0}=0x1
+phy_chain_rx_polarity_flip_physical{72.0}=0x1
+
+#FC19
+phy_chain_rx_polarity_flip_physical{77.0}=0x1
+phy_chain_rx_polarity_flip_physical{78.0}=0x1
+
+#FC21
+phy_chain_rx_polarity_flip_physical{85.0}=0x1
+phy_chain_rx_polarity_flip_physical{86.0}=0x1
+
+#FC23
+phy_chain_rx_polarity_flip_physical{93.0}=0x1
+phy_chain_rx_polarity_flip_physical{94.0}=0x1
+
+#FC24
+phy_chain_rx_polarity_flip_physical{99.0}=0x1
+phy_chain_rx_polarity_flip_physical{100.0}=0x1
+
+#FC26
+phy_chain_rx_polarity_flip_physical{105.0}=0x1
+phy_chain_rx_polarity_flip_physical{106.0}=0x1
+
+#FC28
+phy_chain_rx_polarity_flip_physical{113.0}=0x1
+#phy_chain_rx_polarity_flip_physical{114.0}=0x1
+
+#FC30
+phy_chain_rx_polarity_flip_physical{121.0}=0x1
+phy_chain_rx_polarity_flip_physical{122.0}=0x1
+
+#FC31
+phy_chain_rx_polarity_flip_physical{127.0}=0x1
+phy_chain_rx_polarity_flip_physical{128.0}=0x1
+
+#tx part
+#FC19
+phy_chain_tx_polarity_flip_physical{79.0}=0x1
+phy_chain_tx_polarity_flip_physical{80.0}=0x1
+
+#FC21
+phy_chain_tx_polarity_flip_physical{87.0}=0x1
+phy_chain_tx_polarity_flip_physical{88.0}=0x1
+
+#FC23
+phy_chain_tx_polarity_flip_physical{94.0}=0x1
+phy_chain_tx_polarity_flip_physical{95.0}=0x1
+phy_chain_tx_polarity_flip_physical{96.0}=0x1
+
+#FC24
+phy_chain_tx_polarity_flip_physical{99.0}=0x1
+phy_chain_tx_polarity_flip_physical{100.0}=0x1
+
+#FC26
+phy_chain_tx_polarity_flip_physical{107.0}=0x1
+phy_chain_tx_polarity_flip_physical{108.0}=0x1
+
+#FC28
+phy_chain_tx_polarity_flip_physical{115.0}=0x1
+phy_chain_tx_polarity_flip_physical{116.0}=0x1
+
+#FC30
+phy_chain_tx_polarity_flip_physical{122.0}=0x1
+phy_chain_tx_polarity_flip_physical{123.0}=0x1
+phy_chain_tx_polarity_flip_physical{124.0}=0x1
+
+#FC31
+phy_chain_tx_polarity_flip_physical{127.0}=0x1
+phy_chain_tx_polarity_flip_physical{128.0}=0x1
+
+
+phy_chain_rx_lane_map_physical{1.0}=0x1032
+phy_chain_tx_lane_map_physical{1.0}=0x0123
+phy_chain_rx_lane_map_physical{5.0}=0x1032
+phy_chain_tx_lane_map_physical{5.0}=0x0123
+phy_chain_rx_lane_map_physical{13.0}=0x1032
+phy_chain_tx_lane_map_physical{13.0}=0x0123
+phy_chain_rx_lane_map_physical{21.0}=0x1032
+phy_chain_tx_lane_map_physical{21.0}=0x0123
+phy_chain_rx_lane_map_physical{29.0}=0x1032
+phy_chain_tx_lane_map_physical{29.0}=0x0123
+
+phy_chain_rx_lane_map_physical{33.0}=0x1032
+phy_chain_tx_lane_map_physical{33.0}=0x0123
+phy_chain_rx_lane_map_physical{41.0}=0x1032
+phy_chain_tx_lane_map_physical{41.0}=0x0123
+phy_chain_rx_lane_map_physical{49.0}=0x1032
+phy_chain_tx_lane_map_physical{49.0}=0x0123
+phy_chain_rx_lane_map_physical{57.0}=0x1032
+phy_chain_tx_lane_map_physical{57.0}=0x0123
+phy_chain_rx_lane_map_physical{61.0}=0x1032
+phy_chain_tx_lane_map_physical{61.0}=0x0123
+
+phy_chain_rx_lane_map_physical{65.0}=0x2301
+phy_chain_tx_lane_map_physical{65.0}=0x3210
+phy_chain_rx_lane_map_physical{69.0}=0x2301
+phy_chain_tx_lane_map_physical{69.0}=0x3210
+
+phy_chain_rx_lane_map_physical{85.0}=0x0213
+phy_chain_tx_lane_map_physical{85.0}=0x3120
+phy_chain_rx_lane_map_physical{77.0}=0x2031
+phy_chain_tx_lane_map_physical{77.0}=0x1302
+
+phy_chain_rx_lane_map_physical{93.0}=0x2031
+phy_chain_tx_lane_map_physical{93.0}=0x1302
+phy_chain_rx_lane_map_physical{97.0}=0x0213
+phy_chain_tx_lane_map_physical{97.0}=0x3120
+
+phy_chain_rx_lane_map_physical{113.0}=0x1203
+phy_chain_tx_lane_map_physical{113.0}=0x3120
+phy_chain_rx_lane_map_physical{105.0}=0x2031
+phy_chain_tx_lane_map_physical{105.0}=0x1302
+
+phy_chain_rx_lane_map_physical{121.0}=0x2031
+phy_chain_tx_lane_map_physical{121.0}=0x1302
+phy_chain_rx_lane_map_physical{125.0}=0x0213
+phy_chain_tx_lane_map_physical{125.0}=0x3120
+
+phy_chain_tx_polarity_flip_physical{129.0}=0x0
+phy_chain_rx_polarity_flip_physical{129.0}=0x0
+phy_chain_tx_polarity_flip_physical{130.0}=0x0
+phy_chain_rx_polarity_flip_physical{130.0}=0x0
+phy_chain_tx_polarity_flip_physical{131.0}=0x0
+phy_chain_rx_polarity_flip_physical{131.0}=0x0
+phy_chain_tx_polarity_flip_physical{132.0}=0x0
+phy_chain_rx_polarity_flip_physical{132.0}=0x0
+
+# EQ/IDriver
+serdes_preemphasis_1=0x13460B
+serdes_preemphasis_2=0x13460B
+serdes_preemphasis_3=0x14450B
+serdes_preemphasis_4=0x13460B
+serdes_preemphasis_5=0x11480B
+serdes_preemphasis_6=0x13470A
+serdes_preemphasis_7=0x14460A
+serdes_preemphasis_8=0x11490A
+serdes_preemphasis_13=0x10490B
+serdes_preemphasis_14=0x104A0A
+serdes_preemphasis_15=0x0F4B0A
+serdes_preemphasis_16=0x0F4B0A
+serdes_preemphasis_21=0x0D4D0A
+serdes_preemphasis_22=0x0D4D0A
+serdes_preemphasis_23=0x0D4D0A
+serdes_preemphasis_24=0x0D4D0A
+serdes_preemphasis_29=0x0B4F0A
+serdes_preemphasis_30=0x0D4E09
+serdes_preemphasis_31=0x0B4F0A
+serdes_preemphasis_32=0x0C4F09
+serdes_preemphasis_33=0x0B4F0A
+serdes_preemphasis_34=0x0A5109
+serdes_preemphasis_35=0x09510A
+serdes_preemphasis_36=0x0B5009
+serdes_preemphasis_41=0x09510A
+serdes_preemphasis_42=0x0B5009
+serdes_preemphasis_43=0x09510A
+serdes_preemphasis_44=0x0A5109
+serdes_preemphasis_49=0x0A500A
+serdes_preemphasis_50=0x0B4F0A
+serdes_preemphasis_51=0x09510A
+serdes_preemphasis_52=0x0E4C0A
+serdes_preemphasis_57=0x0D4D0A
+serdes_preemphasis_58=0x0E4D09
+serdes_preemphasis_59=0x0C4E0A
+serdes_preemphasis_60=0x0E4D09
+serdes_preemphasis_61=0x0B4F0A
+serdes_preemphasis_62=0x0D4E09
+serdes_preemphasis_63=0x0D4D0A
+serdes_preemphasis_64=0x0D4D0A
+serdes_preemphasis_67=0x0B4F0A
+serdes_preemphasis_68=0x0C4E0A
+serdes_preemphasis_69=0x0B4F0A
+serdes_preemphasis_70=0x0B4F0A
+serdes_preemphasis_71=0x0B4F0A
+serdes_preemphasis_72=0x0F4B0A
+serdes_preemphasis_73=0x0E4C0A
+serdes_preemphasis_74=0x0F4B0A
+serdes_preemphasis_87=0x0E4C0A
+serdes_preemphasis_79=0x0F4B0A
+serdes_preemphasis_95=0x0F4B0A
+serdes_preemphasis_99=0x0F4B0A
+serdes_preemphasis_115=0x13470A
+serdes_preemphasis_107=0x12480A
+serdes_preemphasis_123=0x154609
+serdes_preemphasis_127=0x13470A
+
+# interface type
+serdes_if_type_1=13
+serdes_if_type_2=13
+serdes_if_type_3=13
+serdes_if_type_4=13
+serdes_if_type_5=13
+serdes_if_type_6=13
+serdes_if_type_7=13
+serdes_if_type_8=13
+serdes_if_type_13=13
+serdes_if_type_14=13
+serdes_if_type_15=13
+serdes_if_type_16=13
+serdes_if_type_21=13
+serdes_if_type_22=13
+serdes_if_type_23=13
+serdes_if_type_24=13
+serdes_if_type_29=13
+serdes_if_type_30=13
+serdes_if_type_31=13
+serdes_if_type_32=13
+serdes_if_type_33=13
+serdes_if_type_34=13
+serdes_if_type_35=13
+serdes_if_type_36=13
+serdes_if_type_41=13
+serdes_if_type_42=13
+serdes_if_type_43=13
+serdes_if_type_44=13
+serdes_if_type_49=13
+serdes_if_type_50=13
+serdes_if_type_51=13
+serdes_if_type_52=13
+serdes_if_type_57=13
+serdes_if_type_58=13
+serdes_if_type_59=13
+serdes_if_type_60=13
+serdes_if_type_61=13
+serdes_if_type_62=13
+serdes_if_type_63=13
+serdes_if_type_64=13
+serdes_if_type_67=13
+serdes_if_type_68=13
+serdes_if_type_69=13
+serdes_if_type_70=13
+serdes_if_type_71=13
+serdes_if_type_72=13
+serdes_if_type_73=13
+serdes_if_type_74=13
+serdes_if_type_87=14
+serdes_if_type_79=14
+serdes_if_type_95=14
+serdes_if_type_99=14
+serdes_if_type_115=14
+serdes_if_type_107=14
+serdes_if_type_123=14
+serdes_if_type_127=14
+
diff --git a/device/inventec/x86_64-inventec_d6356-r0/default_sku b/device/inventec/x86_64-inventec_d6356-r0/default_sku
new file mode 100644
index 000000000000..f4c77ebd10f5
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/default_sku
@@ -0,0 +1 @@
+INVENTEC-D6356 t1
diff --git a/device/inventec/x86_64-inventec_d6356-r0/installer.conf b/device/inventec/x86_64-inventec_d6356-r0/installer.conf
new file mode 100644
index 000000000000..1db64ba02c38
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/installer.conf
@@ -0,0 +1,4 @@
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
+CONSOLE_SPEED=115200
+VAR_LOG_SIZE=1024
diff --git a/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc
new file mode 100644
index 000000000000..d4c2fde64f9c
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc
@@ -0,0 +1,6 @@
+led auto off
+led stop
+m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin
+m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin
+led auto on
+led start
diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..953570d79cd7
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/eeprom.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Inventec d6356
+#
+# Platform and model specific eeprom subclass, inherits from the base class,
+# and provides the followings:
+# - the eeprom format definition
+# - specific encoder/decoder if there is special need
+#############################################################################
+
+try:
+    from sonic_eeprom import eeprom_tlvinfo
+except ImportError, e:
+    raise ImportError (str(e) + "- required module not found")
+
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+
+    def __init__(self, name, path, cpld_root, ro):
+        self.eeprom_path = "/sys/bus/i2c/devices/2-0055/eeprom"
+        super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py
new file mode 100755
index 000000000000..8ed0bce72979
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py
@@ -0,0 +1,84 @@
+#
+# psuutil.py
+# Platform-specific PSU status interface for SONiC
+#
+
+
+import os.path
+
+try:
+    from sonic_psu.psu_base import PsuBase
+except ImportError as e:
+    raise ImportError(str(e) + "- required module not found")
+
+
+class PsuUtil(PsuBase):
+    """Platform-specific PSUutil class"""
+
+    PSU_DIR = "/sys/class/hwmon/hwmon1"
+
+    def __init__(self):
+        PsuBase.__init__(self)
+
+# Get sysfs attribute
+    def get_attr_value(self, attr_path):
+        
+        retval = 'ERR'        
+        if (not os.path.isfile(attr_path)):
+            return retval
+
+        try:
+            with open(attr_path, 'r') as fd:
+                retval = fd.read()
+        except Exception as error:
+            logging.error("Unable to open ", attr_path, " file !")
+
+        retval = retval.rstrip(' \t\n\r')
+        return retval
+    
+    def get_num_psus(self):
+        """
+        Retrieves the number of PSUs available on the device
+        :return: An integer, the number of PSUs available on the device
+         """
+        MAX_PSUS = 2
+        return MAX_PSUS
+
+    def get_psu_status(self, index):
+        """
+        Retrieves the oprational status of power supply unit (PSU) defined
+                by index <index>
+        :param index: An integer, index of the PSU of which to query status
+        :return: Boolean, True if PSU is operating properly, False if PSU is\
+        faulty
+        """
+        status = 0
+        attr_file = 'psoc_psu'+ str(index) + '_iout'        
+        attr_path = self.PSU_DIR +'/' + attr_file
+                  
+        attr_value = self.get_attr_value(attr_path)
+        if (attr_value != 'ERR'):
+            # Check for PSU status
+            if (attr_value != 0):
+                    status = 1
+        return status
+
+    def get_psu_presence(self, index):
+        """
+        Retrieves the presence status of power supply unit (PSU) defined
+                by index <index>
+        :param index: An integer, index of the PSU of which to query status
+        :return: Boolean, True if PSU is plugged, False if not
+        """
+        status = 0
+        psu_absent = 0
+        ind = index
+        attr_file ='psu'+ str(ind)
+        attr_path = self.PSU_DIR +'/' + attr_file
+        normal_attr_value = '0 : normal' 
+        attr_value = self.get_attr_value(attr_path)
+        if (attr_value != 'ERR'):
+            # Check for PSU presence
+            if (attr_value == normal_attr_value):
+                    status = 1
+        return status
diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py
new file mode 100755
index 000000000000..5ea81ffcfc16
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py
@@ -0,0 +1,217 @@
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+
+try:
+    import time
+    from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+    raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+    """Platform-specific SfpUtil class"""
+
+    PORT_START = 0
+    PORT_END = 55
+    PORTS_IN_BLOCK = 56
+    QSFP_PORT_START = 48
+    QSFP_PORT_END = 55
+
+    _port_to_eeprom_mapping = {}
+    port_to_i2c_mapping = {
+        0:22,
+        1:23,
+        2:24,
+        3:25,
+        4:26,
+        5:27,
+        6:28,
+        7:29,
+        8:30,
+        9:31,
+        10:32,
+        11:33,
+        12:34,
+        13:35,
+        14:36,
+        15:37,
+        16:38,
+        17:39,
+        18:40,
+        19:41,
+        20:42,
+        21:43,
+        22:44,
+        23:45,
+        24:46,
+        25:47,
+        26:48,
+        27:49,
+        28:50,
+        29:51,
+        30:52,
+        31:53,
+        32:54,
+        33:55,
+        34:56,
+        35:57,
+        36:58,
+        37:59,
+        38:60,
+        39:61,
+        40:62,
+        41:63,
+        42:64,
+        43:65,
+        44:66,
+        45:67,
+        46:68,
+        47:69,
+        48:14,
+        49:15,
+        50:16,
+        51:17,
+        52:18,
+        53:19,
+        54:20,
+        55:21
+    }
+
+    @property
+    def port_start(self):
+        return self.PORT_START
+
+    @property
+    def port_end(self):
+        return self.PORT_END
+
+    @property
+    def qsfp_port_start(self):
+        return self.QSFP_PORT_START
+
+    @property
+    def qsfp_port_end(self):
+        return self.QSFP_PORT_END
+
+    @property
+    def qsfp_ports(self):
+        return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)
+
+    @property
+    def port_to_eeprom_mapping(self):
+        return self._port_to_eeprom_mapping
+
+    def __init__(self):
+        eeprom_path = "/sys/bus/i2c/devices/{0}-0050/eeprom"
+
+        for x in range(0, self.port_end + 1):
+            port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x])
+            self.port_to_eeprom_mapping[x] = port_eeprom_path
+        SfpUtilBase.__init__(self)
+
+    def get_presence(self, port_num):
+        # Check for invalid port_num
+        if port_num < self.port_start or port_num > self.port_end:
+            return False
+
+        try:
+            reg_file = open("/sys/class/swps/port"+str(port_num)+"/present")
+        except IOError as e:
+            print "Error: unable to open file: %s" % str(e)
+            return False
+
+        reg_value = int(reg_file.readline().rstrip())
+
+        if reg_value == 0:
+            return True
+
+        return False
+
+    def get_low_power_mode(self, port_num):
+        # Check for invalid port_num
+        if port_num < self.port_start or port_num > self.port_end:
+            return False
+        if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+            return False
+
+        try:
+            reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod")
+        except IOError as e:
+            print "Error: unable to open file: %s" % str(e)
+
+        reg_value = int(reg_file.readline().rstrip())
+
+        if reg_value == 0:
+            return False
+
+        return True
+
+    def set_low_power_mode(self, port_num, lpmode):
+        # Check for invalid port_num
+        if port_num < self.port_start or port_num > self.port_end:
+            return False
+        if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+            print "\nError:SFP's don't support this property"
+            return False
+
+        try:
+            reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+")
+        except IOError as e:
+            print "Error: unable to open file: %s" % str(e)
+            return False
+
+        reg_value = int(reg_file.readline().rstrip())
+
+        # LPMode is active high; set or clear the bit accordingly
+        if lpmode is True:
+            reg_value = 1
+        else:
+            reg_value = 0
+
+        reg_file.write(hex(reg_value))
+        reg_file.close()
+
+        return True
+
+    def reset(self, port_num):
+        QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset"
+        # Check for invalid port_num
+        if port_num < self.port_start or port_num > self.port_end:
+            return False
+        if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+            print "\nError:SFP's don't support this property"
+            return False
+
+        try:
+            reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+        except IOError as e:
+            print "Error: unable to open file: %s" % str(e)
+            return False
+
+        reg_value = 0
+        reg_file.write(hex(reg_value))
+        reg_file.close()
+
+        # Sleep 2 second to allow it to settle
+        time.sleep(2)
+
+        # Flip the value back write back to the register to take port out of reset
+        try:
+            reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
+        except IOError as e:
+            print "Error: unable to open file: %s" % str(e)
+            return False
+
+        reg_value = 1
+        reg_file.write(hex(reg_value))
+        reg_file.close()
+
+        return True
+
+    def get_transceiver_change_event(self):
+        """
+        TODO: This function need to be implemented
+        """
+        raise NotImplementedError
diff --git a/device/inventec/x86_64-inventec_d6356-r0/sensors.conf b/device/inventec/x86_64-inventec_d6356-r0/sensors.conf
new file mode 100644
index 000000000000..6f7318168ee6
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6356-r0/sensors.conf
@@ -0,0 +1,106 @@
+# libsensors configuration file
+chip "ucd90160-*"
+     ignore temp1
+
+chip "tmp75-i2c-*-0048"
+     label temp1 "CPU Board Temperature"
+
+chip "tmp75-i2c-*-004a"
+     label temp1 "FrontSide Temperature"
+
+chip "tmp75-i2c-*-004e"
+     label temp1 "NearASIC Temperature"
+
+chip "tmp75-i2c-*-004d"
+     label temp1 "RearSide Temperature"
+
+chip "inv_cpld-i2c-*-77"
+     label fan1 "FanModule1 Front RPM"
+     label fan2 "FanModule1 Rear RPM"
+     label fan3 "FanModule2 Front RPM"
+     label fan4 "FanModule2 Rear RPM"
+     label fan5 "FanModule3 Front RPM"
+     label fan6 "FanModule3 Rear RPM"
+     label fan7 "FanModule4 Front RPM"
+     label fan8 "FanModule4 Rear RPM"
+     label fan9 "FanModule5 Front RPM"
+     label fan10 "FanModule5 Rear RPM"
+     label pwm1 "FanModule1 PWM (0-255)"
+     label pwm2 "FanModule2 PWM (0-255)"
+     label pwm3 "FanModule3 PWM (0-255)"
+     label pwm4 "FanModule4 PWM (0-255)"
+     label pwm5 "FanModule5 PWM (0-255)"
+
+chip "pmbus-i2c-*-005a"
+     ignore power3
+     ignore curr3
+     label fan1 "PSU1 Fan RPM"
+     label temp1 "PSU1 Temperature1"
+     label temp2 "PSU1 Temperature2"
+     label temp3 "PSU1 Temperature3"
+     label in1 "PSU1 Input Voltage"
+     label curr1 "PSU1 Input Current"
+     label power1 "PSU1 Input Power"
+     label in2 "PSU1 Output Voltage"
+     label curr2 "PSU1 Output Current"
+     label power2 "PSU1 Output Power"
+     label pwm1 "PSU1 PWM (0-100)"
+
+chip "pmbus-i2c-*-005b"
+     ignore power3
+     ignore curr3
+     label fan1 "PSU2 Fan RPM"
+     label temp1 "PSU2 Temperature1"
+     label temp2 "PSU2 Temperature2"
+     label temp3 "PSU2 Temperature3"
+     label in1 "PSU2 Input Voltage"
+     label curr1 "PSU2 Input Current"
+     label power1 "PSU2 Input Power"
+     label in2 "PSU2 Output Voltage"
+     label curr2 "PSU2 Output Current"
+     label power2 "PSU2 Output Power"
+     label pwm1 "PSU2 PWM (0-100)"
+
+chip "inv_psoc-*"
+     label temp1 "FrontSide Temperature"
+     label temp2 "FanBoard Temperature"
+     label temp3 "NearASIC Temperature"
+     label temp4 "Center Temperature"
+
+     label temp5 "CPU Board Temperature"
+     label temp6 "ASIC Temperature"
+     label temp7 "PSU1 Temperature1"
+     label temp8 "PSU2 Temperature1"
+     label temp9 "PSU1 Temperature2"
+     label temp10 "PSU2 Temperature2"
+     label fan1 "FanModule1 Front RPM"
+     label fan2 "FanModule1 Rear RPM"
+     label fan3 "FanModule2 Front RPM"
+     label fan4 "FanModule2 Rear RPM"
+     label fan5 "FanModule3 Front RPM"
+     label fan6 "FanModule3 Rear RPM"
+     label fan7 "FanModule4 Front RPM"
+     label fan8 "FanModule4 Rear RPM"
+     label fan9 "FanModule5 Front RPM"
+     label fan10 "FanModule5 Rear RPM"
+     label pwm1 "FanModule1 PWM"
+     label pwm2 "FanModule2 PWM"
+     label pwm3 "FanModule3 PWM"
+     label pwm4 "FanModule4 PWM"
+     label pwm5 "FanModule5 PWM"
+     label pwm6 "PSU1 FAN PWM"
+     label pwm7 "PSU2 FAN PWM"
+     label fan11 "PSU1 FAN RPM"
+     label fan12 "PSU2 FAN RPM"
+     label in1 "PSU1 Input Voltage"
+     label in2 "PSU2 Input Voltage"
+     label curr1 "PSU1 Input Current"
+     label curr2 "PSU2 Input Current"
+     label power1 "PSU1 Input Power"
+     label power2 "PSU2 Input Power"
+     label in3 "PSU1 Output Voltage"
+     label in4 "PSU2 Output Voltage"
+     label curr3 "PSU1 Output Current"
+     label curr4 "PSU2 Output Current"
+     label power3 "PSU1 Output Power"
+     label power4 "PSU2 Output Power"
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index a277c6f59297..9f0babcd3cd8 100755
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -26,6 +26,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
                                $(INVENTEC_D7032Q28B_PLATFORM_MODULE) \
                                $(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
                                $(INVENTEC_D7264Q28B_PLATFORM_MODULE) \
+                               $(INVENTEC_D6356_PLATFORM_MODULE) \
                                $(CEL_DX010_PLATFORM_MODULE) \
                                $(CEL_HALIBURTON_PLATFORM_MODULE) \
                                $(DELTA_AG9032V1_PLATFORM_MODULE) \
diff --git a/platform/broadcom/platform-modules-inventec.mk b/platform/broadcom/platform-modules-inventec.mk
index ead32e75a815..871604ce91d9 100644
--- a/platform/broadcom/platform-modules-inventec.mk
+++ b/platform/broadcom/platform-modules-inventec.mk
@@ -4,12 +4,14 @@ INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION = 1.1.0
 INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION = 1.1.0
 INVENTEC_D6254QS_PLATFORM_MODULE_VERSION = 1.1.0
 INVENTEC_D6556_PLATFORM_MODULE_VERSION = 1.1.0
+INVENTEC_D6356_PLATFORM_MODULE_VERSION = 1.1.0
 INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION = 1.1.0
 
 export INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION
 export INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION
 export INVENTEC_D6254QS_PLATFORM_MODULE_VERSION
 export INVENTEC_D6556_PLATFORM_MODULE_VERSION
+export INVENTEC_D6356_PLATFORM_MODULE_VERSION
 export INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION
 
 INVENTEC_D7032Q28B_PLATFORM_MODULE = platform-modules-d7032q28b_$(INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
@@ -30,8 +32,12 @@ INVENTEC_D6556_PLATFORM_MODULE = platform-modules-d6556_$(INVENTEC_D6556_PLATFOR
 $(INVENTEC_D6556_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6556-r0
 $(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6556_PLATFORM_MODULE)))
 
+INVENTEC_D6356_PLATFORM_MODULE = platform-modules-d6356_$(INVENTEC_D6356_PLATFORM_MODULE_VERSION)_amd64.deb
+$(INVENTEC_D6356_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6356-r0
+$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6356_PLATFORM_MODULE)))
+
 INVENTEC_D7264Q28B_PLATFORM_MODULE = platform-modules-d7264q28b_$(INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
 $(INVENTEC_D7264Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7264q28b-r0
 $(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7264Q28B_PLATFORM_MODULE)))
 
-SONIC_STRETCH_DEBS += $(INVENTEC_D7032Q28B_PLATFORM_MODULE)
\ No newline at end of file
+SONIC_STRETCH_DEBS += $(INVENTEC_D7032Q28B_PLATFORM_MODULE)
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile
new file mode 100755
index 000000000000..23e8295b9026
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile
@@ -0,0 +1,5 @@
+obj-m += inv_cpld.o
+obj-m += inv_platform.o
+obj-m += inv_eeprom.o
+obj-m += swps.o
+swps-objs := inv_swps.o inv_mux.o io_expander.o transceiver.o
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c
new file mode 100644
index 000000000000..8ccaf617b3c4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c
@@ -0,0 +1,950 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/kthread.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/ipmi.h>
+#include <linux/ipmi_smi.h>
+
+/* definition */
+#define CPLD_INFO_OFFSET		0x00
+#define CPLD_BIOSCS_OFFSET		0x04
+#define CPLD_CTL_OFFSET			0x0C
+#define CPLD_LED_OFFSET			0x2E
+#define CPLD_INT_OFFSET			0x30
+#define CPLD_INTMASK_OFFSET		0x31
+#define CPLD_INT2_OFFSET		0x32
+#define CPLD_INTMASK2_OFFSET		0x33
+#define CPLD_PSU_OFFSET			0x40
+#define CPLD_POWERSTATUS_OFFSET		0x41
+#define CPLD_PWM_OFFSET			0x50
+#define CPLD_RPM_OFFSET			0x55
+#define CPLD_FANSTATUS_OFFSET		0x69
+#define CPLD_FANLED_OFFSET		0x6B
+#define CPLD_RESETBUTTONSTATUS_OFFSET	0x75
+#define CPLD_RSTCAUSE_OFFSET		0x76
+#define CPLD_WATCHDOGCOUNTER_OFFSET	0x77
+#define CPLD_WATCHDOGCONFIG_OFFSET	0x78
+#define CPLD_WATCHDOGENABLE_OFFSET	0x79
+#define CPLD_PANICCODE_OFFSET		0x7E
+#define CPLD2_ADDRESS			0x33
+
+#define FAN_NUM				4
+static u8 hasCPLD2 = 1;
+static struct i2c_client *client2;
+
+/* Each client has this additional data */
+struct cpld_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	u8 diag;
+};
+
+/*-----------------------------------------------------------------------*/
+static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count)
+{
+	int i;
+	s32 temp = 0;
+	
+	for(i=0; i<count; i++)
+	{
+		temp = i2c_smbus_read_byte_data(client, offset+i);
+		if(temp<0) 
+		{
+//			printk("CPLD Read fail! Error Code: %d\n",temp);
+			return 0;
+		}
+		buf[i] = temp & 0xff;
+	}
+	return count;
+}
+
+static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
+{   
+	int i;
+	
+	for(i=0; i<count; i++)
+	{
+		i2c_smbus_write_byte_data(client, offset+i, buf[i]);
+	}
+	return count;
+}
+
+/*-----------------------IPMI API--------------------------------------*/
+#define MAX_IPMI_RECV_LENGTH	0xFF
+#define IPMI_MAX_INTF		4
+#define NETFN_OEM 0x30
+#define CMD_GETDATA 0x31
+#define CMD_SETDATA 0x32
+#define IPMI_DIAGFLAG_OFFSET 0x00
+
+struct ipmi_result{
+        char result[MAX_IPMI_RECV_LENGTH];
+        int result_length;
+};
+
+DEFINE_MUTEX(ipmi_mutex);
+DEFINE_MUTEX(ipmi2_mutex);
+static struct ipmi_result ipmiresult;
+static ipmi_user_t ipmi_mh_user = NULL;
+static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data);
+static struct ipmi_user_hndl ipmi_hndlrs = {   .ipmi_recv_hndl = msg_handler,};
+
+static atomic_t dummy_count = ATOMIC_INIT(0);
+static void dummy_smi_free(struct ipmi_smi_msg *msg)
+{
+        atomic_dec(&dummy_count);
+}
+static void dummy_recv_free(struct ipmi_recv_msg *msg)
+{
+        atomic_dec(&dummy_count);
+}
+static struct ipmi_smi_msg halt_smi_msg = {
+        .done = dummy_smi_free
+};
+static struct ipmi_recv_msg halt_recv_msg = {
+        .done = dummy_recv_free
+};
+
+static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data)
+{
+    struct ipmi_result *msg_result = recv_msg->user_msg_data;
+
+    if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) {
+        msg_result->result_length=recv_msg->msg.data_len-1;
+        memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1);
+    }
+    ipmi_free_recv_msg(recv_msg);
+    mutex_unlock(&ipmi_mutex);
+
+    return;
+}
+
+int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length)
+{
+    int rv=0,i;
+    int timeout;
+
+    //wait previous command finish at least 50msec
+    timeout=50;
+    while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); }
+    if(timeout==0) { return -1; }
+    mutex_lock(&ipmi_mutex);
+    mutex_lock(&ipmi2_mutex);
+
+    if(ipmi_mh_user == NULL) {
+        for (i=0,rv=1; i<IPMI_MAX_INTF && rv; i++) {
+            rv = ipmi_create_user(i, &ipmi_hndlrs, NULL, &ipmi_mh_user);
+            }
+    }
+
+    if (rv < 0) {
+        mutex_unlock(&ipmi_mutex);
+        mutex_unlock(&ipmi2_mutex);
+        return rv;
+    }
+    else {
+        struct  ipmi_system_interface_addr addr;
+        struct  kernel_ipmi_msg msg;
+        uint8_t msg_data[data_length];
+
+        memcpy(msg_data,data,data_length);
+        addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
+        addr.channel = IPMI_BMC_CHANNEL;
+        addr.lun = 0;
+
+        msg.netfn = NetFn;
+        msg.cmd = cmd;
+        msg.data = msg_data;
+        msg.data_len = data_length;
+
+        rv = ipmi_request_supply_msgs(ipmi_mh_user, (struct ipmi_addr*)&addr, 0,&msg, &ipmiresult, &halt_smi_msg, &halt_recv_msg, 0);
+        if (rv) {
+                mutex_unlock(&ipmi_mutex);
+                mutex_unlock(&ipmi2_mutex);
+                return -6;
+        }
+
+        //skip command if 1sec no response from remote
+        timeout=1000;
+        while(mutex_is_locked(&ipmi_mutex) == 1 && (--timeout)>0) { usleep_range(1000,1100);}
+        if(timeout==0) {
+                mutex_unlock(&ipmi2_mutex);
+                return -1;
+        }
+        else {
+                *result_length=ipmiresult.result_length;
+                memcpy(result,ipmiresult.result,*result_length);
+                mutex_unlock(&ipmi2_mutex);
+                return 0;
+        }
+    }
+    return 0;
+}
+EXPORT_SYMBOL(start_ipmi_command);
+
+/*-----------------------------------------------------------------------*/
+/* sysfs attributes for hwmon */
+static ssize_t show_info(struct device *dev, struct device_attribute *da,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+
+	u8 byte[4] = {0,0,0,0};
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, byte, CPLD_INFO_OFFSET, 4);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", 
+	byte[2] & 0xf, (byte[3] & 0x1f), 2014+(byte[2] >> 4));	/* mm/dd/yyyy*/
+	sprintf (buf, "%sThe PCB  version is %X\n", buf,  byte[0]&0xf);
+	sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf);
+
+	if(hasCPLD2) {
+		mutex_lock(&data->update_lock);
+		cpld_i2c_read(client2, byte, CPLD_INFO_OFFSET, 4);
+		mutex_unlock(&data->update_lock);
+
+		sprintf (buf, "%s\nThe CPLD2 release date is %02d/%02d/%d.\n", buf, 
+		byte[2] & 0xf, (byte[3] & 0x1f), 2014+(byte[2] >> 4));	/* mm/dd/yyyy*/
+		sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf);
+	}
+	
+	return strlen(buf);
+}
+
+static char* powerstatus_str[] = {
+    "Failed",     //0
+    "Good",       //1
+};
+
+static ssize_t show_powerstatus(struct device *dev, struct device_attribute *da,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte[2] = {0,0};
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, byte, CPLD_POWERSTATUS_OFFSET, 2);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	sprintf (buf, "PGD_P5V_STBY: %s\n", powerstatus_str[(byte[0]>>7) & 0x01]);
+	sprintf (buf, "%sPGD_P3V3_STBY: %s\n", buf, powerstatus_str[(byte[0]>>6) & 0x01]);;
+	sprintf (buf, "%sPGD_P1V8_A: %s\n", buf, powerstatus_str[(byte[0]>>4) & 0x01]);
+	sprintf (buf, "%sPGD_P3V3_SYS: %s\n", buf, powerstatus_str[(byte[0]>>3) & 0x01]);
+	sprintf (buf, "%sPGD_P3V3_A: %s\n", buf, powerstatus_str[(byte[0]>>2) & 0x01]);
+	sprintf (buf, "%sPGD_P3V3_B: %s\n", buf, powerstatus_str[(byte[0]>>1) & 0x01]);
+	sprintf (buf, "%sPGD_P1V2: %s\n", buf, powerstatus_str[(byte[0]>>0) & 0x01]);
+	sprintf (buf, "%sPGD_P0V8_A: %s\n", buf,powerstatus_str[(byte[1]>>7) & 0x01]);
+	sprintf (buf, "%sPGD_P0V89_ROV: %s\n", buf, powerstatus_str[(byte[1]>>6) & 0x01]);
+	sprintf (buf, "%sSW_PWR_READY: %s\n", buf, powerstatus_str[(byte[1]>>3) & 0x01]);
+	sprintf (buf, "%sCORE_PWRGD_TO_CPLD: %s\n", buf, powerstatus_str[(byte[1]>>2) & 0x01]);
+	sprintf (buf, "%sCPU_STBY_PWROK: %s\n", buf, powerstatus_str[(byte[1]>>1) & 0x01]);
+
+	return strlen(buf);
+}
+
+static ssize_t show_diag(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	uint8_t ipmisend[]= { IPMI_DIAGFLAG_OFFSET, 1};
+	uint8_t result[MAX_IPMI_RECV_LENGTH];
+	int result_len=0;
+	start_ipmi_command(NETFN_OEM, CMD_GETDATA,ipmisend, 2, result, &result_len);
+	data->diag = (result[0] & 0x80) !=0;
+	return sprintf (buf, "%d\n", data->diag);
+}
+
+static ssize_t set_diag(struct device *dev,
+			   struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	uint8_t ipmisend[]= { IPMI_DIAGFLAG_OFFSET, 0x80};
+	uint8_t result[MAX_IPMI_RECV_LENGTH];
+	int result_len=0;
+	u8 diag = simple_strtol(buf, NULL, 10);
+	data->diag = diag?1:0;
+	if (data->diag==0) ipmisend[1] = 0x00;
+
+	start_ipmi_command(NETFN_OEM, CMD_SETDATA,ipmisend, 2, result, &result_len);
+
+	return count;
+}
+
+static char* resetbutton_str[] = {
+    "No press",     		//0
+    "Reserved",      		//1
+    "Press and hold <5s",  	//2
+    "Press and hold >5s",   	//3
+};
+
+static ssize_t show_resetbuttonstatus(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte = 0;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, &byte, CPLD_RESETBUTTONSTATUS_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	byte &=0x03;
+
+	return sprintf (buf, "0x%02X:%s\n", byte,resetbutton_str[byte]);
+}
+
+static char* interrupt_str[] = {
+    "CPU_SEN_ALERT_N", 		//0
+    "EXT_USB_OC_N",      	//1
+    "PS2_ALERT_N",  		//2
+    "PS1_ALERT_N",    		//3
+    "PLD_SEN5_ALERT_N",		//4
+    "PLD_SEN4_ALERT_N",     	//5
+    "PLD_SEN3_ALERT_N",  	//6
+    "UCD90160_TEMP_INT_N",    	//7
+    "RSTBTN_INT_N",		//8
+    "WDT_IRQ_N",  		//9
+    "RSTBTN_5s_INT_N",    	//10
+    "Reserved"			//11
+};
+
+static ssize_t show_interrupt(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte[4] = {0,0,0,0};
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, byte, CPLD_INT_OFFSET, 4);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	sprintf (buf, "0x%02X 0x%02X:", byte[0],byte[2]);
+	if(byte[0]==0xff && byte[2]==0x07) sprintf (buf, "%sNone",buf);
+	if(!(byte[0]&0x01)) sprintf (buf, "%s%s ",buf,interrupt_str[0]);
+	if(!(byte[0]&0x02)) sprintf (buf, "%s%s ",buf,interrupt_str[1]);
+	if(!(byte[0]&0x04)) sprintf (buf, "%s%s ",buf,interrupt_str[2]);
+	if(!(byte[0]&0x08)) sprintf (buf, "%s%s ",buf,interrupt_str[3]);
+	if(!(byte[0]&0x10)) sprintf (buf, "%s%s ",buf,interrupt_str[4]);
+	if(!(byte[0]&0x20)) sprintf (buf, "%s%s ",buf,interrupt_str[5]);
+	if(!(byte[0]&0x40)) sprintf (buf, "%s%s ",buf,interrupt_str[6]);
+	if(!(byte[0]&0x80)) sprintf (buf, "%s%s ",buf,interrupt_str[7]);
+	if(!(byte[2]&0x01)) sprintf (buf, "%s%s%s ",buf,interrupt_str[8] ,(byte[3]&0x01)?"(Blocked)":"");
+	if(!(byte[2]&0x02)) sprintf (buf, "%s%s%s ",buf,interrupt_str[9] ,(byte[3]&0x02)?"(Blocked)":"");
+	if(!(byte[2]&0x04)) sprintf (buf, "%s%s%s ",buf,interrupt_str[10],(byte[3]&0x04)?"(Blocked)":"");
+
+	return sprintf (buf, "%s\n", buf);
+}
+
+static char* bios_str[] = {
+    "BIOS1",     	//0
+    "BIOS2",      	//1
+};
+
+static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da,
+                         char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte = 0;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	byte &= 0x01;
+
+	return sprintf (buf, "%d:%s\n", byte,bios_str[byte]);
+}
+
+static ssize_t set_bios_cs(struct device *dev,
+                           struct device_attribute *da,
+                           const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	u8 byte = 0;
+	u8 temp = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1);
+	if(temp) byte |= 0x01; else byte &= ~(0x01);
+	cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static char* led_str[] = {
+    "OFF",     //000
+    "ON",      //001
+    "1 Hz",    //010
+    "2 Hz",    //011
+};
+
+static ssize_t show_led(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte = 0;
+	int shift = attr->index;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	byte = (byte >> shift) & 0x3;
+	
+	return sprintf (buf, "%d: %s\n", byte, led_str[byte]);
+}
+
+static ssize_t set_led(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+
+	u8 temp = simple_strtol(buf, NULL, 16);
+	u8 byte = 0;
+	int shift = attr->index;  
+	temp &= 0x3;
+
+	mutex_lock(&data->update_lock);
+	cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+	byte &= ~(0x3<<shift);
+	byte |= (temp<<shift);
+	cpld_i2c_write(client, &byte, CPLD_LED_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static char* psu_str[] = {
+    "unpowered",        //00
+    "normal",           //01
+    "not installed",    //10
+    "not installed",    //11
+};
+
+static ssize_t show_psu(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte=0;
+	int shift = (attr->index == 0)?0:4;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client2, &byte, CPLD_PSU_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	byte = (byte >> shift) & 0x3;
+
+	return sprintf (buf, "%d:%s\n", byte, psu_str[byte]);
+}
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte=0;
+	u8 offset = attr->index  + CPLD_PWM_OFFSET;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client2, &byte, offset, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	return sprintf(buf, "%d\n", byte);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	u8 offset = attr->index  + CPLD_PWM_OFFSET;
+	u8 byte = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	cpld_i2c_write(client2, &byte, offset, 1);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_rpm(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 offset = attr->index*2  + CPLD_RPM_OFFSET;
+	u8 byte[2] = {0,0};
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client2, byte, offset, 2);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	return sprintf(buf, "%d\n", (byte[0]<<8 | byte[1]));
+}
+
+static char* fantype_str[] = {
+    "Normal Type",   //00
+    "REVERSAL Type", //01
+    "UNPLUGGED",     //10
+    "UNPLUGGED",     //11
+};
+
+static ssize_t show_fantype(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	int status;
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 offset = CPLD_FANSTATUS_OFFSET;
+	u8 byte[2] = {0,0};
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client2, byte, offset, 2);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+	status = (((byte[0] >> attr->index) & 0x01)) | (((byte[1] >> attr->index) & 0x01)<<1);
+
+	return sprintf(buf, "%d:%s\n",status,fantype_str[status]);
+}
+
+static char* fanled_str[] = {
+    "None",   //00
+    "Green",  //01
+    "Red",    //10
+    "Both",   //11
+};
+
+static ssize_t show_fanled(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	int status;
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte[2] = {0,0};
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client2, byte, CPLD_FANLED_OFFSET, 2);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+	status = (((byte[0] >> attr->index) & 0x01)) | (((byte[1] >> attr->index) & 0x01)<<1);
+
+	return sprintf(buf, "%d:%s\n",status,fanled_str[status]);
+}
+
+static ssize_t set_fanled(struct device *dev,
+			   struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	u8 byte[2] = {0,0};	
+	u8 temp = simple_strtol(buf, NULL, 16);	
+	int shift = attr->index;
+
+	temp &= 0x3;
+	mutex_lock(&data->update_lock);
+	cpld_i2c_read(client2, byte, CPLD_FANLED_OFFSET, 2);
+	byte[0] &= ~(1<<shift);
+	byte[1] &= ~(1<<shift);
+	byte[0] |= (temp & 0x01)<<shift;
+	byte[1] |= ((temp >> 1) & 0x01)<<shift;
+	cpld_i2c_write(client, byte, CPLD_FANLED_OFFSET, 2);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t set_watchdog_feed(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	u8 byte=0;
+
+	mutex_lock(&data->update_lock);
+	cpld_i2c_read(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1);
+	byte |= 0x02;
+	cpld_i2c_write(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t set_watchdog_enable(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	u8 byte=0x03;
+
+	mutex_lock(&data->update_lock);
+	cpld_i2c_write(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_watchdog_enable(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte=0;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, &byte, CPLD_WATCHDOGENABLE_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	return sprintf(buf, "%d\n",(byte&0x01));
+}
+
+static ssize_t set_watchdog_config(struct device *dev,
+			   struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	u8 byte = simple_strtol(buf, NULL, 10);
+
+	if (byte<6) byte=6; 
+	mutex_lock(&data->update_lock);
+	cpld_i2c_write(client, &byte, CPLD_WATCHDOGCONFIG_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_watchdog_config(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte=0;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, &byte, CPLD_WATCHDOGCONFIG_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	return sprintf(buf, "%d seconds\n",byte);
+}
+
+static ssize_t show_watchdog_counter(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct cpld_data *data = i2c_get_clientdata(client);
+	ssize_t len = 0;
+	u8 byte=0;
+
+	mutex_lock(&data->update_lock);
+	len = cpld_i2c_read(client, &byte, CPLD_WATCHDOGCOUNTER_OFFSET, 1);
+	mutex_unlock(&data->update_lock);
+	if (len==0) return 0;
+
+	return sprintf(buf, "%d seconds\n",byte);
+}
+
+static SENSOR_DEVICE_ATTR(info,         S_IRUGO,		show_info, 0, 0);
+static SENSOR_DEVICE_ATTR(diag, 	S_IWUSR|S_IRUGO,	show_diag, set_diag, 0);
+static SENSOR_DEVICE_ATTR(interrupt, 	S_IRUGO,   		show_interrupt, 0, 0);
+
+static SENSOR_DEVICE_ATTR(stacking_led, S_IWUSR|S_IRUGO,   show_led, set_led, 0);
+static SENSOR_DEVICE_ATTR(fan_led,      S_IWUSR|S_IRUGO,   show_led, set_led, 2);
+static SENSOR_DEVICE_ATTR(power_led,    S_IWUSR|S_IRUGO,   show_led, set_led, 4);
+static SENSOR_DEVICE_ATTR(service_led,  S_IWUSR|S_IRUGO,   show_led, set_led, 6);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO,	show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO,	show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO,	show_pwm, set_pwm, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO,	show_pwm, set_pwm, 3);
+#if FAN_NUM>4
+static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO,	show_pwm, set_pwm, 4);
+#endif
+
+static SENSOR_DEVICE_ATTR(fanmodule1_type, S_IRUGO,	show_fantype, 0, 0);
+static SENSOR_DEVICE_ATTR(fanmodule2_type, S_IRUGO,	show_fantype, 0, 1);
+static SENSOR_DEVICE_ATTR(fanmodule3_type, S_IRUGO,	show_fantype, 0, 2);
+static SENSOR_DEVICE_ATTR(fanmodule4_type, S_IRUGO,	show_fantype, 0, 3);
+#if FAN_NUM>4
+static SENSOR_DEVICE_ATTR(fanmodule5_type, S_IRUGO,	show_fantype, 0, 4);
+#endif
+
+static SENSOR_DEVICE_ATTR(fanmodule1_led, S_IWUSR|S_IRUGO,	show_fanled, set_fanled, 0);
+static SENSOR_DEVICE_ATTR(fanmodule2_led, S_IWUSR|S_IRUGO,	show_fanled, set_fanled, 1);
+static SENSOR_DEVICE_ATTR(fanmodule3_led, S_IWUSR|S_IRUGO,	show_fanled, set_fanled, 2);
+static SENSOR_DEVICE_ATTR(fanmodule4_led, S_IWUSR|S_IRUGO,	show_fanled, set_fanled, 3);
+#if FAN_NUM>4
+static SENSOR_DEVICE_ATTR(fanmodule5_led, S_IWUSR|S_IRUGO,	show_fanled, set_fanled, 4);
+#endif
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO,	show_rpm, 0, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO,	show_rpm, 0, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO,	show_rpm, 0, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO,	show_rpm, 0, 3);
+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO,	show_rpm, 0, 4);
+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO,	show_rpm, 0, 5);
+static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO,	show_rpm, 0, 6);
+static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO,	show_rpm, 0, 7);
+#if FAN_NUM>4
+static SENSOR_DEVICE_ATTR(fan9_input, S_IRUGO,	show_rpm, 0, 8);
+static SENSOR_DEVICE_ATTR(fan10_input,S_IRUGO,	show_rpm, 0, 9);
+#endif
+
+static SENSOR_DEVICE_ATTR(psu1,         S_IRUGO,           	show_psu, 0, 0);
+static SENSOR_DEVICE_ATTR(psu2,         S_IRUGO,           	show_psu, 0, 1);
+static SENSOR_DEVICE_ATTR(power_status, S_IRUGO,           	show_powerstatus, 0, 0);
+static SENSOR_DEVICE_ATTR(resetbutton_status,  S_IRUGO,		show_resetbuttonstatus, 0, 0);
+
+static SENSOR_DEVICE_ATTR(watchdog_feed,	S_IWUSR,		0, set_watchdog_feed, 0);
+static SENSOR_DEVICE_ATTR(watchdog_enable,	S_IWUSR|S_IRUGO,	show_watchdog_enable, set_watchdog_enable, 0);
+static SENSOR_DEVICE_ATTR(watchdog_config,	S_IWUSR|S_IRUGO,	show_watchdog_config, set_watchdog_config, 0);
+static SENSOR_DEVICE_ATTR(watchdog_counter,	S_IRUGO,           	show_watchdog_counter,  0, 0);
+
+static SENSOR_DEVICE_ATTR(bios_cs,      	S_IWUSR|S_IRUGO,   	show_bios_cs, set_bios_cs, 0);
+			
+static struct attribute *cpld_attributes[] = {
+	&sensor_dev_attr_info.dev_attr.attr,
+	&sensor_dev_attr_diag.dev_attr.attr,
+	
+	&sensor_dev_attr_stacking_led.dev_attr.attr,
+	&sensor_dev_attr_fan_led.dev_attr.attr,
+	&sensor_dev_attr_power_led.dev_attr.attr,
+	&sensor_dev_attr_service_led.dev_attr.attr,
+
+	&sensor_dev_attr_interrupt.dev_attr.attr,
+	
+	&sensor_dev_attr_psu1.dev_attr.attr,
+	&sensor_dev_attr_psu2.dev_attr.attr,
+	&sensor_dev_attr_power_status.dev_attr.attr,
+	&sensor_dev_attr_resetbutton_status.dev_attr.attr,
+	
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
+	&sensor_dev_attr_pwm4.dev_attr.attr,
+#if FAN_NUM>4
+	&sensor_dev_attr_pwm5.dev_attr.attr,
+#endif	
+	&sensor_dev_attr_fanmodule1_type.dev_attr.attr,
+	&sensor_dev_attr_fanmodule2_type.dev_attr.attr,
+	&sensor_dev_attr_fanmodule3_type.dev_attr.attr,
+	&sensor_dev_attr_fanmodule4_type.dev_attr.attr,
+#if FAN_NUM>4
+	&sensor_dev_attr_fanmodule5_type.dev_attr.attr,
+#endif	
+	&sensor_dev_attr_fanmodule1_led.dev_attr.attr,
+	&sensor_dev_attr_fanmodule2_led.dev_attr.attr,
+	&sensor_dev_attr_fanmodule3_led.dev_attr.attr,
+	&sensor_dev_attr_fanmodule4_led.dev_attr.attr,
+#if FAN_NUM>4
+	&sensor_dev_attr_fanmodule5_led.dev_attr.attr,
+#endif	
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan5_input.dev_attr.attr,
+	&sensor_dev_attr_fan6_input.dev_attr.attr,
+	&sensor_dev_attr_fan7_input.dev_attr.attr,
+	&sensor_dev_attr_fan8_input.dev_attr.attr,
+#if FAN_NUM>4
+	&sensor_dev_attr_fan9_input.dev_attr.attr,
+	&sensor_dev_attr_fan10_input.dev_attr.attr,
+#endif
+	&sensor_dev_attr_watchdog_feed.dev_attr.attr,
+	&sensor_dev_attr_watchdog_enable.dev_attr.attr,
+	&sensor_dev_attr_watchdog_config.dev_attr.attr,
+	&sensor_dev_attr_watchdog_counter.dev_attr.attr,
+	
+	&sensor_dev_attr_bios_cs.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group cpld_group = {
+	.attrs = cpld_attributes,
+};
+
+/*-----------------------------------------------------------------------*/
+/* device probe and removal */
+static int
+cpld_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct cpld_data *data;
+	int status;
+	u8 byte[5];
+   
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+		return -EIO;
+
+	data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Register sysfs hooks */
+	status = sysfs_create_group(&client->dev.kobj, &cpld_group);
+
+	if (status)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		status = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	//Check CPLD2 exist or not 
+	client2 = i2c_new_dummy(client->adapter, CPLD2_ADDRESS);
+	if(!client2) {
+		hasCPLD2 = 0;
+		client2 = client;
+	} else {
+		status = i2c_smbus_read_byte_data(client2, CPLD_INFO_OFFSET);
+		if(status<0) {
+			i2c_unregister_device(client2);
+			i2c_set_clientdata(client2, NULL);
+			hasCPLD2 = 0;
+			client2 = client;		
+		}
+	}
+
+	//Handle LED control by the driver
+	byte[0]=0x01;
+	cpld_i2c_write(client, byte, CPLD_CTL_OFFSET, 1);
+	cpld_i2c_write(client2, byte, CPLD_CTL_OFFSET, 1);
+
+	dev_info(&client->dev, "%s: sensor '%s'\n",
+		 dev_name(data->hwmon_dev), client->name);
+	
+	return 0;
+
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &cpld_group);
+exit_free:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return status;
+}
+
+static int cpld_remove(struct i2c_client *client)
+{	
+	struct cpld_data *data = i2c_get_clientdata(client);
+
+	sysfs_remove_group(&client->dev.kobj, &cpld_group);
+	hwmon_device_unregister(data->hwmon_dev);
+	i2c_set_clientdata(client, NULL);
+	if(hasCPLD2) {
+		i2c_unregister_device(client2);
+		i2c_set_clientdata(client2, NULL);
+	}
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id cpld_ids[] = {
+	{ "inv_cpld" , 0, },
+	{ /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, cpld_ids);
+
+static struct i2c_driver cpld_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "inv_cpld",
+	},
+	.probe		= cpld_probe,
+	.remove		= cpld_remove,
+	.id_table	= cpld_ids,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* module glue */
+
+static int __init inv_cpld_init(void)
+{
+	return i2c_add_driver(&cpld_driver);
+}
+
+static void __exit inv_cpld_exit(void)
+{
+	i2c_del_driver(&cpld_driver);
+}
+
+MODULE_AUTHOR("jack.ting <ting.jack@inventec>");
+MODULE_DESCRIPTION("cpld driver");
+MODULE_LICENSE("GPL");
+
+module_init(inv_cpld_init);
+module_exit(inv_cpld_exit);
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_eeprom.c
new file mode 100644
index 000000000000..7bb167d2e74e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_eeprom.c
@@ -0,0 +1,181 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+
+/* Size of EEPROM in bytes */
+#define EEPROM_SIZE		256
+
+#define SLICE_BITS		(6)
+#define SLICE_SIZE		(1 << SLICE_BITS)
+#define SLICE_NUM		(EEPROM_SIZE/SLICE_SIZE)
+
+/* Each client has this additional data */
+struct eeprom_data {
+	struct mutex update_lock;
+	u8 valid;			/* bitfield, bit!=0 if slice is valid */
+	unsigned long last_updated[SLICE_NUM];	/* In jiffies, 8 slices */
+	u8 data[EEPROM_SIZE];		/* Register values */
+};
+
+
+static void inv_eeprom_update_client(struct i2c_client *client, u8 slice)
+{
+	struct eeprom_data *data = i2c_get_clientdata(client);
+	int i, j;
+	int ret;
+	int addr;
+	
+
+	mutex_lock(&data->update_lock);
+
+	if (!(data->valid & (1 << slice)) ||
+	    time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
+		dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
+
+		addr = slice << SLICE_BITS;
+
+		ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF);
+		/* select the eeprom address */
+		if (ret < 0) {
+			dev_err(&client->dev, "address set failed\n");
+			goto exit;
+		}
+
+		if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) {
+			goto exit;
+		}
+
+		for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) {
+			for (j = i; j < (i+SLICE_SIZE); j++) {
+				int res;
+
+				res = i2c_smbus_read_byte(client);
+				if (res < 0) {
+					goto exit;
+				}
+
+				data->data[j] = res & 0xFF;
+			}
+		}
+		
+		data->last_updated[slice] = jiffies;
+		data->valid |= (1 << slice);
+	}
+
+exit:
+	mutex_unlock(&data->update_lock);
+}
+
+static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj,
+			   struct bin_attribute *bin_attr,
+			   char *buf, loff_t off, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+	struct eeprom_data *data = i2c_get_clientdata(client);
+	u8 slice;
+	
+
+	if (off > EEPROM_SIZE) {
+		return 0;
+	}
+	if (off + count > EEPROM_SIZE) {
+		count = EEPROM_SIZE - off;
+	}
+	if (count == 0) {
+		return 0;
+	}
+
+	/* Only refresh slices which contain requested bytes */
+	for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) {
+		inv_eeprom_update_client(client, slice);
+	}
+
+	memcpy(buf, &data->data[off], count);
+
+	return count;
+}
+
+static struct bin_attribute inv_eeprom_attr = {
+	.attr = {
+		.name = "eeprom",
+		.mode = S_IRUGO,
+	},
+	.size = EEPROM_SIZE,
+	.read = inv_eeprom_read,
+};
+
+static int inv_eeprom_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct eeprom_data *data;
+	int err;
+	
+	if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	memset(data->data, 0xff, EEPROM_SIZE);
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* create the sysfs eeprom file */
+	err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+	if (err) {
+		goto exit_kfree;
+	}
+	
+	return 0;
+
+exit_kfree:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int inv_eeprom_remove(struct i2c_client *client)
+{
+	sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr);
+	kfree(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static const struct i2c_device_id inv_eeprom_id[] = {
+	{ "inv_eeprom", 0 },
+	{ }
+};
+
+static struct i2c_driver inv_eeprom_driver = {
+	.driver = {
+		.name	= "inv_eeprom",
+	},
+	.probe		= inv_eeprom_probe,
+	.remove		= inv_eeprom_remove,
+	.id_table	= inv_eeprom_id,
+};
+
+module_i2c_driver(inv_eeprom_driver);
+
+MODULE_AUTHOR("Inventec");
+MODULE_DESCRIPTION("Inventec D6556 Mother Board EEPROM driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c
new file mode 100644
index 000000000000..a303527bec46
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c
@@ -0,0 +1,281 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <asm/io.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include "io_expander.h"
+#include "inv_mux.h"
+
+static struct mux_obj_s *mux_head_p = NULL;
+
+
+/* ========== MUX object functions ==========
+ */
+int
+_common_force_pull_gpio(int mem_addr,
+                        int input,
+                        int bit_offset){
+
+    unsigned int val  = 0;
+    unsigned int targ = 0;
+
+    /* Get current value */
+    val = inl(mem_addr);
+    if (val == 0) {
+        SWPS_ERR("%s: inl:%d fail!\n", __func__, val);
+        return -1;
+    }
+    /* Count target value */
+    switch (input) {
+        case 0: /* Pull Low */
+            targ = (val & (~(1 << bit_offset)));
+            break;
+        case 1: /* Pull high */
+            targ = (val | (1 << bit_offset));
+            break;
+        default:
+            SWPS_ERR("%s: input state:%d incorrect!\n",
+                    __func__, input);
+            return -1;
+    }
+    /* Setup gpio */
+    outl(targ, mem_addr);
+    if (targ != inl(mem_addr)){
+        SWPS_ERR("%s: outl:%d fail!\n", __func__, targ);
+        return -1;
+    }
+    SWPS_DEBUG("%s: done.\n", __func__);
+    return 0;
+}
+
+
+int
+rangeley_force_pull_high(struct mux_obj_s *self){
+    SWPS_ERR("%s: not ready!\n", __func__);
+    return -1;
+}
+
+
+int
+rangeley_force_pull_low(struct mux_obj_s *self){
+    SWPS_ERR("%s: not ready!\n", __func__);
+    return -1;
+}
+
+
+int
+hedera_force_pull_high(struct mux_obj_s *self){
+    return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5);
+}
+
+
+int
+hedera_force_pull_low(struct mux_obj_s *self){
+    return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5);
+}
+
+
+int
+normal_gpio_pull_high(struct mux_obj_s *self){
+    return gpio_direction_output(self->gpio_num, 1);
+}
+
+
+int
+normal_gpio_pull_low(struct mux_obj_s *self){
+    return gpio_direction_output(self->gpio_num, 0);
+}
+
+
+int
+pca9548_reset_mux_all(struct mux_obj_s *self){
+    /* [Note] Power-on reset (PCA9548A-NXP)
+     *     When power is applied to VDD, an internal Power-On Reset (POR)
+     *     holds the PCA9548A in a reset condition until VDD has reached
+     *     VPOR. At this point, the reset condition is released and the
+     *     PCA9548A register and I2C-bus state machine are initialized to
+     *     their default states (all zeroes) causing all the channels to
+     *     be deselected. Thereafter, VDD must be lowered below 0.2 V for
+     *     at least 5 us in order to reset the device.
+     */
+    if (self->_pull_low(self) < 0) {
+        SWPS_ERR("%s: _pull_low fail!\n", __func__);
+        return -1;
+    }
+    mdelay(MUX_RST_WAIT_MS);
+    if (self->_pull_high(self) < 0) {
+        SWPS_ERR("%s: _pull_high fail!\n", __func__);
+        return -1;
+    }
+    mdelay(MUX_RST_WAIT_MS);
+    return 0;
+}
+
+
+int
+common_reset_mux_all(struct mux_obj_s *self){
+    SWPS_ERR("%s: not ready!\n", __func__);
+    return -1;
+}
+
+
+int
+init_gpio_4_force(struct mux_obj_s *self){
+    return 0;
+}
+
+
+int
+init_gpio_4_normal(struct mux_obj_s *self){
+
+    int err = 0;
+
+    if (!gpio_is_valid(self->gpio_num)) {
+        SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num);
+        return -1;
+    }
+    err = gpio_request(self->gpio_num, MUX_GPIO_LABEL);
+    if (err < 0) {
+        SWPS_ERR("%s: gpio_request fail <err>:%d <gpio>:%d\n",
+                 __func__, err, self->gpio_num);
+        return -1;
+    }
+    SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num);
+    return 0;
+}
+
+
+static int
+_setup_muxctl_cb(struct mux_obj_s *self,
+                 unsigned gpio){
+
+    char mod_dsc[32] = "ERR";
+
+    switch (gpio) {
+        case MUX_RST_GPIO_FORCE_RANGELEY:
+            self->gpio_num   = gpio;
+            self->_pull_low  = rangeley_force_pull_low;
+            self->_pull_high = rangeley_force_pull_high;
+            self->_init      = init_gpio_4_force;
+            self->reset      = pca9548_reset_mux_all;
+            memset(mod_dsc, 0, 32);
+            snprintf(mod_dsc, 31, "Rangeley force mode");
+            goto ok_setup_muxctl_cb;
+
+        case MUX_RST_GPIO_FORCE_HEDERA:
+            self->gpio_num   = gpio;
+            self->_pull_low  = hedera_force_pull_low;
+            self->_pull_high = hedera_force_pull_high;
+            self->_init      = init_gpio_4_force;
+            self->reset      = pca9548_reset_mux_all;
+            memset(mod_dsc, 0, 32);
+            snprintf(mod_dsc, 31, "Hedera force mode");
+            goto ok_setup_muxctl_cb;
+
+        case MUX_RST_GPIO_48_PAC9548:
+        case MUX_RST_GPIO_69_PAC9548:
+        case MUX_RST_GPIO_249_PCA9548:
+        case MUX_RST_GPIO_500_PAC9548:
+        case MUX_RST_GPIO_505_PCA9548:
+            self->gpio_num   = gpio;
+            self->_pull_low  = normal_gpio_pull_low;
+            self->_pull_high = normal_gpio_pull_high;
+            self->_init      = init_gpio_4_normal;
+            self->reset      = pca9548_reset_mux_all;
+            memset(mod_dsc, 0, 32);
+            snprintf(mod_dsc, 31, "Normal mode <gpio>:%d", (int)gpio);
+            goto ok_setup_muxctl_cb;
+
+        default:
+            break;
+    }
+    SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio);
+    return -1;
+
+ok_setup_muxctl_cb:
+    SWPS_INFO("muxctl: %s.\n", mod_dsc);
+    return 0;
+}
+
+
+/* ========== MUX public functions ==========
+ */
+void
+clean_mux_gpio(void){
+
+    if (!mux_head_p) {
+        SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__);
+        return;
+    }
+    if (gpio_is_valid(mux_head_p->gpio_num)) {
+        gpio_free(mux_head_p->gpio_num);
+    }
+    kfree(mux_head_p);
+    mux_head_p = NULL;
+    SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+int
+reset_mux_gpio(void){
+
+    if (!mux_head_p) {
+        SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__);
+        return -1;
+    }
+    if (mux_head_p->reset(mux_head_p) < 0){
+        SWPS_ERR("%s: reset fail!\n", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+
+int
+init_mux_gpio(unsigned gpio){
+
+    /* Create MUX control object */
+    if (mux_head_p) {
+        SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__);
+        clean_mux_gpio();
+    }
+    /* Currently, it is using single muxctl architecture.
+     * In the future, it may use the multi-muxctl if HW add new features.
+     * (Ex: Port power-status control)
+     */
+    mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL);
+    if (!mux_head_p) {
+        SWPS_ERR("%s: kzalloc fail!\n", __func__);
+        return -1;
+    }
+    /* Initial MUX controller */
+    if (_setup_muxctl_cb(mux_head_p, gpio) < 0){
+        SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__);
+        return -1;
+    }
+    if (mux_head_p->_init(mux_head_p) < 0) {
+        SWPS_ERR("%s: init() fail\n", __func__);
+        goto err_init_mux_gpio;
+    }
+    /* Setup default value */
+    if (mux_head_p->_pull_high(mux_head_p) < 0) {
+        SWPS_ERR("%s: setup default fail!\n", __func__);
+        goto err_init_mux_gpio;
+    }
+    return 0;
+
+err_init_mux_gpio:
+    clean_mux_gpio();
+    return -1;
+}
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h
new file mode 100644
index 000000000000..f981a304644a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h
@@ -0,0 +1,47 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef INV_MUX_H
+#define INV_MUX_H
+
+
+/* MUX basic information */
+#define MUX_GPIO_LABEL                 "SWPS_RST_MUX"
+
+/* MUX reset GPIO define */
+#define MUX_RST_GPIO_FORCE            (30100)
+#define MUX_RST_GPIO_FORCE_RANGELEY   (30101)
+#define MUX_RST_GPIO_FORCE_HEDERA     (30102)
+#define MUX_RST_GPIO_48_PAC9548          (48)
+#define MUX_RST_GPIO_69_PAC9548          (69)
+#define MUX_RST_GPIO_249_PCA9548        (249)
+#define MUX_RST_GPIO_500_PAC9548        (500)
+#define MUX_RST_GPIO_505_PCA9548        (505)
+
+/* MUX relate value define */
+#define MUX_RST_WAIT_MS                   (1)
+#define MUX_RST_MEM_ADDR_RANGELEY         (0)    // TBD
+#define MUX_RST_MEM_ADDR_HEDERA       (0x548)
+
+struct mux_obj_s {
+    unsigned gpio_num;
+    int (*_pull_high)(struct mux_obj_s *self);
+    int (*_pull_low)(struct mux_obj_s *self);
+    int (*_init)(struct mux_obj_s *self);
+    int (*reset)(struct mux_obj_s *self);
+};
+
+
+void clean_mux_gpio(void);
+int  reset_mux_gpio(void);
+int  init_mux_gpio(unsigned gpio);
+
+
+#endif /* INV_MUX_H */
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c
new file mode 100644
index 000000000000..42900232dca8
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c
@@ -0,0 +1,275 @@
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/i2c/pca954x.h>
+
+struct inv_i2c_board_info {
+    int ch;
+    int size;
+    struct i2c_board_info *board_info;
+};
+
+#define bus_id(id)  (id)
+static struct pca954x_platform_mode pca9641_modes_1[] = {
+    {.adap_id = bus_id(2),},
+};
+
+static struct pca954x_platform_mode pca9641_modes_2[] = {
+    {.adap_id = bus_id(5),},
+};
+
+static struct pca954x_platform_mode pca9641_modes_3[] = {
+    {.adap_id = bus_id(3),},
+};
+
+static struct pca954x_platform_mode pca9641_modes_4[] = {
+    {.adap_id = bus_id(4),},
+};
+
+static struct pca954x_platform_mode mux_modes_0[] = {
+    {.adap_id = bus_id(6),},    {.adap_id = bus_id(7),},
+    {.adap_id = bus_id(8),},    {.adap_id = bus_id(9),},
+    {.adap_id = bus_id(10),},    {.adap_id = bus_id(11),},
+    {.adap_id = bus_id(12),},    {.adap_id = bus_id(13),},
+};
+static struct pca954x_platform_mode mux_modes_0_0[] = {
+    {.adap_id = bus_id(14),},    {.adap_id = bus_id(15),},
+    {.adap_id = bus_id(16),},    {.adap_id = bus_id(17),},
+    {.adap_id = bus_id(18),},    {.adap_id = bus_id(19),},
+    {.adap_id = bus_id(20),},    {.adap_id = bus_id(21),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_1[] = {
+    {.adap_id = bus_id(22),},    {.adap_id = bus_id(23),},
+    {.adap_id = bus_id(24),},    {.adap_id = bus_id(25),},
+    {.adap_id = bus_id(26),},    {.adap_id = bus_id(27),},
+    {.adap_id = bus_id(28),},    {.adap_id = bus_id(29),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_2[] = {
+    {.adap_id = bus_id(30),},    {.adap_id = bus_id(31),},
+    {.adap_id = bus_id(32),},    {.adap_id = bus_id(33),},
+    {.adap_id = bus_id(34),},    {.adap_id = bus_id(35),},
+    {.adap_id = bus_id(36),},    {.adap_id = bus_id(37),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_3[] = {
+    {.adap_id = bus_id(38),},    {.adap_id = bus_id(39),},
+    {.adap_id = bus_id(40),},    {.adap_id = bus_id(41),},
+    {.adap_id = bus_id(42),},    {.adap_id = bus_id(43),},
+    {.adap_id = bus_id(44),},    {.adap_id = bus_id(45),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_4[] = {
+    {.adap_id = bus_id(46),},    {.adap_id = bus_id(47),},
+    {.adap_id = bus_id(48),},    {.adap_id = bus_id(49),},
+    {.adap_id = bus_id(50),},    {.adap_id = bus_id(51),},
+    {.adap_id = bus_id(52),},    {.adap_id = bus_id(53),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_5[] = {
+    {.adap_id = bus_id(54),},    {.adap_id = bus_id(55),},
+    {.adap_id = bus_id(56),},    {.adap_id = bus_id(57),},
+    {.adap_id = bus_id(58),},    {.adap_id = bus_id(59),},
+    {.adap_id = bus_id(60),},    {.adap_id = bus_id(61),},
+};
+
+static struct pca954x_platform_mode mux_modes_0_6[] = {
+    {.adap_id = bus_id(62),},    {.adap_id = bus_id(63),},
+    {.adap_id = bus_id(64),},    {.adap_id = bus_id(65),},
+    {.adap_id = bus_id(66),},    {.adap_id = bus_id(67),},
+    {.adap_id = bus_id(68),},    {.adap_id = bus_id(69),},
+};
+
+//no i2c device driver attach to mux 7
+
+static struct pca954x_platform_data pca9641_data_1 = {
+        .modes          = pca9641_modes_1,
+        .num_modes      = 1,
+};
+static struct pca954x_platform_data pca9641_data_2 = {
+        .modes          = pca9641_modes_2,
+        .num_modes      = 1,
+};
+static struct pca954x_platform_data pca9641_data_3 = {
+        .modes          = pca9641_modes_3,
+        .num_modes      = 1,
+};
+static struct pca954x_platform_data pca9641_data_4 = {
+        .modes          = pca9641_modes_4,
+        .num_modes      = 1,
+};
+static struct pca954x_platform_data mux_data_0 = {
+        .modes          = mux_modes_0,
+        .num_modes      = 8,
+};
+static struct pca954x_platform_data mux_data_0_0 = {
+        .modes          = mux_modes_0_0,
+        .num_modes      = 8,
+};
+static struct pca954x_platform_data mux_data_0_1 = {
+        .modes          = mux_modes_0_1,
+        .num_modes      = 8,
+};
+static struct pca954x_platform_data mux_data_0_2 = {
+        .modes          = mux_modes_0_2,
+        .num_modes      = 8,
+};
+static struct pca954x_platform_data mux_data_0_3 = {
+        .modes          = mux_modes_0_3,
+        .num_modes      = 8,
+};
+static struct pca954x_platform_data mux_data_0_4 = {
+        .modes          = mux_modes_0_4,
+        .num_modes      = 8,
+};
+static struct pca954x_platform_data mux_data_0_5 = {
+        .modes          = mux_modes_0_5,
+        .num_modes      = 8,
+};
+static struct pca954x_platform_data mux_data_0_6 = {
+        .modes          = mux_modes_0_6,
+        .num_modes      = 8,
+};
+
+static struct i2c_board_info i2c_device_info0[] __initdata = {
+	{"pca9641",	     0, 0x76, &pca9641_data_1, 0, 0},	//PCA9641-1
+	{"pca9641",	     0, 0x73, &pca9641_data_3, 0, 0},	//PCA9641-3
+	{"pca9641",	     0, 0x09, &pca9641_data_4, 0, 0},	//PCA9641-4
+};
+static struct i2c_board_info i2c_device_info1[] __initdata = {
+	{"pca9641",	     0, 0x0A, &pca9641_data_2, 0, 0},	//PCA9641-2
+};
+static struct i2c_board_info i2c_device_info2[] __initdata = {
+       {"inv_cpld",         0, 0x77, 0, 0, 0},			//CPLD
+};
+static struct i2c_board_info i2c_device_info3[] __initdata = {
+	{"tmp75",            0, 0x48, 0, 0, 0},                 //CPU Board Temp
+	{"tmp75",            0, 0x4A, 0, 0, 0},                 //Temp
+	{"tmp75",            0, 0x4D, 0, 0, 0},                 //Temp
+	{"tmp75",            0, 0x4E, 0, 0, 0},                 //Temp
+};
+static struct i2c_board_info i2c_device_info4[] __initdata = {
+	{"pmbus",	     0, 0x5A, 0, 0, 0},			//PSU1
+	{"pmbus",	     0, 0x5B, 0, 0, 0},			//PSU2
+};
+static struct i2c_board_info i2c_device_info5[] __initdata = {
+	{"pca9548",          0, 0x70, &mux_data_0, 0, 0},	//mux root
+};
+static struct i2c_board_info i2c_device_info6[] __initdata = {
+        {"pca9548",         0, 0x72, &mux_data_0_0, 0, 0},	
+};
+static struct i2c_board_info i2c_device_info7[] __initdata = {
+        {"pca9548",         0, 0x72, &mux_data_0_1, 0, 0},	
+};
+static struct i2c_board_info i2c_device_info8[] __initdata = {
+        {"pca9548",         0, 0x72, &mux_data_0_2, 0, 0},	
+};
+static struct i2c_board_info i2c_device_info9[] __initdata = {
+        {"pca9548",         0, 0x72, &mux_data_0_3, 0, 0},	
+};
+static struct i2c_board_info i2c_device_info10[] __initdata = {
+        {"pca9548",         0, 0x72, &mux_data_0_4, 0, 0},	
+};
+static struct i2c_board_info i2c_device_info11[] __initdata = {
+        {"pca9548",         0, 0x72, &mux_data_0_5, 0, 0},	
+};
+static struct i2c_board_info i2c_device_info12[] __initdata = {
+        {"pca9548",         0, 0x72, &mux_data_0_6, 0, 0},	
+};
+
+
+static struct inv_i2c_board_info i2cdev_list[] = {
+    {bus_id(0), ARRAY_SIZE(i2c_device_info0),  i2c_device_info0 },  //SMBus
+    {bus_id(1), ARRAY_SIZE(i2c_device_info1),  i2c_device_info1 },  //pca9641-2
+    {bus_id(2), ARRAY_SIZE(i2c_device_info2),  i2c_device_info2 },  //pca9641-1
+    {bus_id(3), ARRAY_SIZE(i2c_device_info3),  i2c_device_info3 },  //pca9641-3
+    {bus_id(4), ARRAY_SIZE(i2c_device_info4),  i2c_device_info4 },  //pca9641-4
+    {bus_id(5), ARRAY_SIZE(i2c_device_info5),  i2c_device_info5 },  //mux root
+    {bus_id(6), ARRAY_SIZE(i2c_device_info6),  i2c_device_info6 },  //mux CH0
+    {bus_id(7), ARRAY_SIZE(i2c_device_info7),  i2c_device_info7 },  //mux CH1
+    {bus_id(8), ARRAY_SIZE(i2c_device_info8),  i2c_device_info8 },  //mux CH2
+    {bus_id(9), ARRAY_SIZE(i2c_device_info9),  i2c_device_info9 },  //mux CH3
+    {bus_id(10),ARRAY_SIZE(i2c_device_info10), i2c_device_info10},  //mux CH4
+    {bus_id(11),ARRAY_SIZE(i2c_device_info11), i2c_device_info11},  //mux CH5
+    {bus_id(12),ARRAY_SIZE(i2c_device_info12), i2c_device_info12},  //mux CH6  
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+static struct   platform_device         *device_i2c_gpio0;
+static struct 	i2c_gpio_platform_data 	i2c_gpio_platdata0 = {
+	.scl_pin = 58, //494,
+	.sda_pin = 75, //511,
+    
+	.udelay  = 5, //5:100kHz
+	.sda_is_open_drain = 0,
+	.scl_is_open_drain = 0,
+	.scl_is_output_only = 0
+};
+
+static int __init inv_platform_init(void)
+{
+    struct i2c_adapter *adap = NULL;
+    struct i2c_client *e = NULL;
+    int ret = 0;
+    int i,j,k;
+
+    //printk("%s  \n", __func__);
+
+    //use i2c-gpio    
+    //register i2c gpio
+    //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5
+    outl( inl(0x533) | (1<<2), 0x533);  //i2c-gpio sdl (GPIO58)
+    outl( inl(0x541) | (1<<3), 0x541);  //i2c-gpio sda (GPIO75)
+    outl( inl(0x540) | (1<<5), 0x540);  //RST_I2C_MUX_N (GPIO69)
+    outl( inl(0x500) | (1<<7), 0x500);  //SYS_RDY_N (GPIO7)
+    outl( inl(0x501) | (1<<7), 0x501);  //BMC_HEART_BEAT (GPIO15)
+    outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27)
+   
+    device_i2c_gpio0 = platform_device_alloc("i2c-gpio", 1);
+    if (!device_i2c_gpio0) {
+        printk(KERN_ERR "i2c-gpio: platform_device_alloc fail\n");
+        return -ENOMEM;
+    }
+    device_i2c_gpio0->name = "i2c-gpio";
+    device_i2c_gpio0->id     = 1;
+    device_i2c_gpio0->dev.platform_data = &i2c_gpio_platdata0;
+
+    ret = platform_device_add(device_i2c_gpio0);
+    if (ret) {
+        printk(KERN_ERR "i2c-gpio: platform_device_add fail %d\n", ret);
+    }
+   msleep(10);
+   for(i=0; i<ARRAY_SIZE(i2cdev_list); i++) {
+        adap = i2c_get_adapter( i2cdev_list[i].ch );
+        if (adap == NULL) {
+            printk("platform get channel %d adapter fail\n", i);
+            continue;
+        }
+        i2c_put_adapter(adap);
+        for(j=0; j<i2cdev_list[i].size; j++) {
+            for(k=0; k<300; k++) {
+                e = i2c_new_device(adap, &i2cdev_list[i].board_info[j] );
+                if(e == NULL) msleep(10); else break;
+            }
+        }
+    }
+    return ret;    
+}
+
+static void __exit inv_platform_exit(void)
+{
+	device_i2c_gpio0->dev.platform_data = NULL;
+	platform_device_unregister(device_i2c_gpio0);
+}
+
+module_init(inv_platform_init);
+module_exit(inv_platform_exit);
+
+MODULE_AUTHOR("Inventec");
+MODULE_DESCRIPTION("Platform devices");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c
new file mode 100644
index 000000000000..cbb22fba2979
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c
@@ -0,0 +1,3049 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/dmi.h>
+#include "inv_swps.h"
+
+static int ctl_major;
+static int port_major;
+static int ioexp_total;
+static int port_total;
+static int auto_config;
+static int flag_i2c_reset;
+static int flag_mod_state;
+static unsigned gpio_rest_mux;
+static struct class *swp_class_p = NULL;
+static struct inv_platform_s *platform_p = NULL;
+static struct inv_ioexp_layout_s *ioexp_layout = NULL;
+static struct inv_port_layout_s *port_layout = NULL;
+
+static void swp_polling_worker(struct work_struct *work);
+static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker);
+
+static int reset_i2c_topology(void);
+
+
+static int
+__swp_match(struct device *dev,
+#ifdef SWPS_KERN_VER_AF_3_10
+
+            const void *data){
+#else
+            void *data){
+#endif
+
+    char *name = (char *)data;
+    if (strcmp(dev_name(dev), name) == 0)
+        return 1;
+    return 0;
+}
+
+
+struct device *
+get_swpdev_by_name(char *name){
+    struct device *dev = class_find_device(swp_class_p,
+                                           NULL,
+                                           name,
+                                           __swp_match);
+    return dev;
+}
+
+
+static int
+sscanf_2_int(const char *buf) {
+
+    int   result  = -EBFONT;
+    char *hex_tag = "0x";
+
+    if (strcspn(buf, hex_tag) == 0) {
+        if (sscanf(buf,"%x",&result)) {
+            return result;
+        }
+    } else {
+        if (sscanf(buf,"%d",&result)) {
+            return result;
+        }
+        if(sscanf(buf,"-%d",&result)) {
+            return -result;
+        }
+        if (sscanf(buf,"%x",&result)) {
+            return result;
+        }
+    }
+    return -EBFONT;
+}
+
+
+static int
+sscanf_2_binary(const char *buf) {
+
+    int result = sscanf_2_int(buf);
+
+    if (result < 0){
+        return -EBFONT;
+    }
+    switch (result) {
+        case 0:
+        case 1:
+            return result;
+        default:
+            break;
+    }
+    return -EBFONT;
+}
+
+
+static int
+_get_polling_period(void) {
+
+    int retval = 0;
+
+    if (SWP_POLLING_PERIOD == 0) {
+        return 0;
+    }
+    retval = ((SWP_POLLING_PERIOD * HZ) / 1000);
+    if (retval == 0) {
+        return 1;
+    }
+    return retval;
+}
+
+
+static struct transvr_obj_s *
+_get_transvr_obj(char *dev_name) {
+
+    struct device *dev_p = NULL;
+    struct transvr_obj_s *transvr_obj_p = NULL;
+
+    dev_p = get_swpdev_by_name(dev_name);
+    if (!dev_p){
+        return NULL;
+    }
+    transvr_obj_p = dev_get_drvdata(dev_p);
+    if (!transvr_obj_p){
+        return NULL;
+    }
+    return transvr_obj_p;
+}
+
+
+static void
+unlock_tobj_all(void) {
+
+    struct transvr_obj_s *tobj_p;
+    char port_name[32];
+    int  port_id = 0;
+    int  minor_curr = 0;
+
+    for (minor_curr=0; minor_curr<port_total; minor_curr++) {
+        port_id = port_layout[minor_curr].port_id;
+        memset(port_name, 0, sizeof(port_name));
+        snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id);
+        tobj_p = _get_transvr_obj(port_name);
+        if (!tobj_p) {
+            continue;
+        }
+        unlock_transvr_obj(tobj_p);
+    }
+}
+
+
+static int
+lock_tobj_all(void) {
+
+    struct transvr_obj_s *tobj_p;
+    char port_name[32] = "ERR";
+    int  port_id    = 0;
+    int  minor_curr = 0;
+
+    for (minor_curr=0; minor_curr<port_total; minor_curr++) {
+        port_id = port_layout[minor_curr].port_id;
+        memset(port_name, 0, sizeof(port_name));
+        snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id);
+        tobj_p = _get_transvr_obj(port_name);
+        if (!tobj_p) {
+            SWPS_DEBUG("%s: get %s tobj fail!\n", __func__, port_name);
+            goto err_lock_tobj_all;
+        }
+        lock_transvr_obj(tobj_p);
+    }
+    return 0;
+
+err_lock_tobj_all:
+    unlock_tobj_all();
+    return -1;
+}
+
+
+static int
+_update_auto_config_2_trnasvr(void) {
+    
+    struct transvr_obj_s *tobj_p;
+    char port_name[32] = "ERR";
+    int port_id = 0;
+    int curr    = 0;
+    int retval  = 0;
+        
+    for (curr=0; curr<port_total; curr++) {
+        port_id = port_layout[curr].port_id;
+        memset(port_name, 0, sizeof(port_name));
+        snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id);
+        tobj_p = _get_transvr_obj(port_name);
+        if (!tobj_p) {
+            retval = -1;
+            continue;
+        }
+        lock_transvr_obj(tobj_p);
+        tobj_p->auto_config = auto_config;
+        unlock_transvr_obj(tobj_p);
+        SWPS_DEBUG("%s: Set %s auto_config=%d\n",
+                   __func__, tobj_p->swp_name, auto_config);
+    }
+    return retval;
+}
+
+
+/* ========== R/W Functions module control attribute ==========
+ */
+static ssize_t
+show_attr_platform(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    return snprintf(buf_p, 32, "%s\n", platform_p->name);
+}
+
+
+static ssize_t
+show_attr_version(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    return snprintf(buf_p, 8, "%s\n", SWP_VERSION);
+}
+
+
+static ssize_t
+show_attr_status(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 char *buf_p){
+
+    return snprintf(buf_p, 8, "%d\n", flag_mod_state);
+}
+
+
+static ssize_t
+show_attr_auto_config(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      char *buf_p){
+
+    return snprintf(buf_p, 8, "%d\n", auto_config);
+}
+
+
+static int
+_check_reset_pwd(const char *buf_p,
+                 size_t count) {
+
+    int  in_max = 64;
+    int  in_len = (int)count;
+    char in_val[64] = "ERR";
+    char *emsg = "ERR";
+
+    if (in_len >= in_max) {
+        emsg = "input too much";
+        goto err_check_reset_pwd;
+    }
+    if (!sscanf(buf_p,"%s",in_val)) {
+        emsg = "format incorrect";
+        goto err_check_reset_pwd;
+    }
+    if (strcmp(in_val, SWP_RESET_PWD) != 0) {
+        emsg = "password incorrect";
+        goto err_check_reset_pwd;
+    }
+    return 0;
+
+err_check_reset_pwd:
+    SWPS_ERR("%s: %s\n", __func__, emsg);
+    return -1;
+}
+
+
+static ssize_t
+store_attr_reset_i2c(struct device *dev_p,
+                     struct device_attribute *attr_p,
+                     const char *buf_p,
+                     size_t count){
+
+    if (_check_reset_pwd(buf_p, count) < 0) {
+        return -EBFONT;
+    }
+    /* Polling mode */
+    if (SWP_POLLING_ENABLE) {
+        SWPS_INFO("%s: reset I2C <mode>:polling\n", __func__);
+        flag_i2c_reset = 1;
+        return count;
+    }
+    /* Direct mode */
+    SWPS_INFO("%s: reset I2C go. <mode>:direct\n", __func__);
+    if (reset_i2c_topology() < 0) {
+        SWPS_ERR("%s: reset fail!\n", __func__);
+        return -EIO;
+    }
+    SWPS_INFO("%s: reset I2C ok. <mode>:direct\n", __func__);
+    return count;
+}
+
+
+static ssize_t
+store_attr_reset_swps(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      const char *buf_p,
+                      size_t count){
+
+    struct transvr_obj_s *tobj_p;
+    char port_name[32] = "ERR";
+    int  port_id    = 0;
+    int  minor_curr = 0;
+
+    if (_check_reset_pwd(buf_p, count) < 0) {
+        return -EBFONT;
+    }
+    for (minor_curr=0; minor_curr<port_total; minor_curr++) {
+        port_id = port_layout[minor_curr].port_id;
+        memset(port_name, 0, sizeof(port_name));
+        snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id);
+        tobj_p = _get_transvr_obj(port_name);
+        if (!tobj_p) {
+            continue;
+        }
+        lock_transvr_obj(tobj_p);
+        tobj_p->state = STATE_TRANSVR_DISCONNECTED;
+        unlock_transvr_obj(tobj_p);
+        SWPS_INFO("%s: reset:%s\n", __func__, tobj_p->swp_name);
+    }
+    return count;
+}
+
+
+static ssize_t
+store_attr_auto_config(struct device *dev_p,
+                       struct device_attribute *attr_p,
+                       const char *buf_p,
+                       size_t count){
+
+    int input_val = sscanf_2_int(buf_p);
+    
+    if (input_val < 0){
+        return -EBFONT;
+    }
+    if ((input_val != 0) && (input_val != 1)) {
+        return -EBFONT;
+    }
+    auto_config = input_val;
+    _update_auto_config_2_trnasvr();
+    return count;
+}
+
+
+/* ========== Show functions: For transceiver attribute ==========
+ */
+static ssize_t
+_show_transvr_hex_attr(struct transvr_obj_s* tobj_p,
+                       int (*get_func)(struct transvr_obj_s* tobj_p),
+                       char *buf_p) {
+    size_t len;
+    int result;
+
+    lock_transvr_obj(tobj_p);
+    result = get_func(tobj_p);
+    unlock_transvr_obj(tobj_p);
+    if (result < 0){
+        len = snprintf(buf_p, 8, "%d\n", result);
+    } else {
+        len = snprintf(buf_p, 8, "0x%02x\n", result);
+    }
+    return len;
+}
+
+
+static ssize_t
+_show_transvr_int_attr(struct transvr_obj_s* tobj_p,
+                       int (*get_func)(struct transvr_obj_s* tobj_p),
+                       char *buf_p) {
+    size_t len;
+
+    lock_transvr_obj(tobj_p);
+    len = snprintf(buf_p, 16, "%d\n", get_func(tobj_p));
+    unlock_transvr_obj(tobj_p);
+    return len;
+}
+
+
+static ssize_t
+_show_transvr_str_attr(struct transvr_obj_s* tobj_p,
+                       int (*get_func)(struct transvr_obj_s* tobj_p, char* buf),
+                       char *buf_p) {
+    size_t len;
+
+    lock_transvr_obj(tobj_p);
+    len = get_func(tobj_p, buf_p);
+    unlock_transvr_obj(tobj_p);
+    return len;
+}
+
+
+static ssize_t
+show_attr_id(struct device *dev_p,
+             struct device_attribute *attr_p,
+             char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_id,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_ext_id(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_ext_id,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_connector(struct device *dev_p,
+                    struct device_attribute *attr_p,
+                    char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_connector,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_vendor_name(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_vendor_name,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_vendor_pn(struct device *dev_p,
+                    struct device_attribute *attr_p,
+                    char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_vendor_pn,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_vendor_rev(struct device *dev_p,
+                     struct device_attribute *attr_p,
+                     char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_vendor_rev,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_vendor_sn(struct device *dev_p,
+                    struct device_attribute *attr_p,
+                    char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_vendor_sn,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_power_cls(struct device *dev_p,
+                    struct device_attribute *attr_p,
+                    char *buf_p){
+    size_t len;
+    int result;
+    struct transvr_obj_s *tobj_p;
+
+    tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    lock_transvr_obj(tobj_p);
+    result = tobj_p->get_power_cls(tobj_p);
+    unlock_transvr_obj(tobj_p);
+    if (result < 0){
+        len = snprintf(buf_p, 16, "%d\n", result);
+    } else {
+        len = snprintf(buf_p, 16, "Power Class %d\n", result);
+    }
+    return len;
+}
+
+
+static ssize_t
+show_attr_br(struct device *dev_p,
+             struct device_attribute *attr_p,
+             char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_br,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_len_sm(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_len_sm,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_len_smf(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_len_smf,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_len_om1(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_len_om1,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_len_om2(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_len_om2,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_len_om3(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_len_om3,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_len_om4(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_len_om4,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_comp_rev(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_comp_rev,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_comp_eth(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_comp_eth_1,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_comp_eth_10(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_comp_eth_10,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_comp_eth_10_40(struct device *dev_p,
+                         struct device_attribute *attr_p,
+                         char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_comp_eth_10_40,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_comp_extend(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_comp_extend,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_rate_id(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_rate_id,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_temperature(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_curr_temp,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_voltage(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_curr_vol,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_tx_bias(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_tx_bias,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_tx_power(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_tx_power,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_tx_eq(struct device *dev_p,
+                struct device_attribute *attr_p,
+                char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_tx_eq,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_rx_power(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_rx_power,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_rx_am(struct device *dev_p,
+                struct device_attribute *attr_p,
+                char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_rx_am,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_rx_em(struct device *dev_p,
+                struct device_attribute *attr_p,
+                char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_rx_em,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_wavelength(struct device *dev_p,
+                     struct device_attribute *attr_p,
+                     char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_wavelength,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_extphy_offset(struct device *dev_p,
+                        struct device_attribute *attr_p,
+                        char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_extphy_offset,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_extphy_reg(struct device *dev_p,
+                     struct device_attribute *attr_p,
+                     char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_extphy_reg,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_info(struct device *dev_p,
+               struct device_attribute *attr_p,
+               char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_info,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_if_type(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_if_type,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_if_speed(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_if_speed,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_if_lane(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_if_lane,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_cdr(struct device *dev_p,
+              struct device_attribute *attr_p,
+              char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_hex_attr(tobj_p,
+                                  tobj_p->get_cdr,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_soft_rs0(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_soft_rs0,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_soft_rs1(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_int_attr(tobj_p,
+                                  tobj_p->get_soft_rs1,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_soft_rx_los(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_soft_rx_los,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_soft_tx_disable(struct device *dev_p,
+                          struct device_attribute *attr_p,
+                          char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_soft_tx_disable,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_soft_tx_fault(struct device *dev_p,
+                        struct device_attribute *attr_p,
+                        char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_soft_tx_fault,
+                                  buf_p);
+}
+
+
+static ssize_t
+show_attr_auto_tx_disable(struct device *dev_p,
+                          struct device_attribute *attr_p,
+                          char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if(!tobj_p){
+        return -ENODEV;
+    }
+    return _show_transvr_str_attr(tobj_p,
+                                  tobj_p->get_auto_tx_disable,
+                                  buf_p);
+}
+
+
+/* ========== Store functions: transceiver (R/W) attribute ==========
+ */
+static ssize_t
+_store_transvr_int_attr(struct transvr_obj_s* tobj_p,
+                        int (*set_func)(struct transvr_obj_s *tobj_p, int input_val),
+                        const char *buf_p,
+                        size_t count) {
+    int input, err;
+
+    input = sscanf_2_int(buf_p);
+    if (input < 0){
+        return -EBFONT;
+    }
+    lock_transvr_obj(tobj_p);
+    err = set_func(tobj_p, input);
+    unlock_transvr_obj(tobj_p);
+    if (err < 0){
+        return err;
+    }
+    return count;
+}
+
+
+static ssize_t
+_store_transvr_byte_hex_attr(struct transvr_obj_s* tobj_p,
+                             int (*set_func)(struct transvr_obj_s *tobj_p, int input_val),
+                             const char *buf_p,
+                             size_t count) {
+    int input, err;
+
+    input = sscanf_2_int(buf_p);
+    if ((input < 0) || (input > 0xff)){
+        return -EBFONT;
+    }
+    lock_transvr_obj(tobj_p);
+    err = set_func(tobj_p, input);
+    unlock_transvr_obj(tobj_p);
+    if (err < 0){
+        return err;
+    }
+    return count;
+}
+
+
+static ssize_t
+_store_transvr_binary_attr(struct transvr_obj_s* tobj_p,
+                           int (*set_func)(struct transvr_obj_s *tobj_p, int input_val),
+                           const char *buf_p,
+                           size_t count) {
+    int input, err;
+
+    input = sscanf_2_binary(buf_p);
+    if (input < 0){
+        return -EBFONT;
+    }
+    lock_transvr_obj(tobj_p);
+    err = set_func(tobj_p, input);
+    unlock_transvr_obj(tobj_p);
+    if (err < 0){
+        return err;
+    }
+    return count;
+}
+
+
+static ssize_t
+store_attr_cdr(struct device *dev_p,
+               struct device_attribute *attr_p,
+               const char *buf_p,
+               size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_byte_hex_attr(tobj_p,
+                                        tobj_p->set_cdr,
+                                        buf_p,
+                                        count);
+}
+
+
+static ssize_t
+store_attr_soft_rs0(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   const char *buf_p,
+                   size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_binary_attr(tobj_p,
+                                      tobj_p->set_soft_rs0,
+                                      buf_p,
+                                      count);
+}
+
+
+static ssize_t
+store_attr_soft_rs1(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   const char *buf_p,
+                   size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_binary_attr(tobj_p,
+                                      tobj_p->set_soft_rs1,
+                                      buf_p,
+                                      count);
+}
+
+
+static ssize_t
+store_attr_soft_tx_disable(struct device *dev_p,
+                           struct device_attribute *attr_p,
+                           const char *buf_p,
+                           size_t count) {
+
+    int check = sscanf_2_int(buf_p);
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    if ((check < 0) || (check > 0xf)){
+        return -EBFONT;
+    }
+    return _store_transvr_byte_hex_attr(tobj_p,
+                                        tobj_p->set_soft_tx_disable,
+                                        buf_p,
+                                        count);
+}
+
+
+static ssize_t
+store_attr_auto_tx_disable(struct device *dev_p,
+                           struct device_attribute *attr_p,
+                           const char *buf_p,
+                           size_t count) {
+
+    int err   = -EPERM;
+    int input = sscanf_2_int(buf_p);
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    if ((input < 0) || (input > 0xf)){
+        if (input != VAL_TRANSVR_FUNCTION_DISABLE) {
+            return -EBFONT;
+        }
+    }
+    lock_transvr_obj(tobj_p);
+    err = tobj_p->set_auto_tx_disable(tobj_p, input);
+    unlock_transvr_obj(tobj_p);
+    if (err < 0){
+        return err;
+    }
+    return count;
+}
+
+
+static ssize_t
+store_attr_tx_eq(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 const char *buf_p,
+                 size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_int_attr(tobj_p,
+                                   tobj_p->set_tx_eq,
+                                   buf_p,
+                                   count);
+}
+
+
+static ssize_t
+store_attr_rx_am(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 const char *buf_p,
+                 size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_int_attr(tobj_p,
+                                   tobj_p->set_rx_am,
+                                   buf_p,
+                                   count);
+}
+
+
+static ssize_t
+store_attr_rx_em(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 const char *buf_p,
+                 size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_int_attr(tobj_p,
+                                   tobj_p->set_rx_em,
+                                   buf_p,
+                                   count);
+}
+
+
+static ssize_t
+store_attr_extphy_offset(struct device *dev_p,
+                         struct device_attribute *attr_p,
+                         const char *buf_p,
+                         size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_int_attr(tobj_p,
+                                   tobj_p->set_extphy_offset,
+                                   buf_p,
+                                   count);
+}
+
+
+static ssize_t
+store_attr_extphy_reg(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      const char *buf_p,
+                      size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _store_transvr_int_attr(tobj_p,
+                                   tobj_p->set_extphy_reg,
+                                   buf_p,
+                                   count);
+}
+
+/* ========== Show functions: For I/O Expander attribute ==========
+ */
+static ssize_t
+_show_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+                        int (*get_func)(struct ioexp_obj_s *ioexp_p, int voffset),
+                        char *buf_p) {
+    size_t len;
+    struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+    if (!ioexp_p) {
+        SWPS_ERR(" %s: data corruption! <port>:%s\n", __func__, tobj_p->swp_name);
+        return -ENODATA;
+    }
+    mutex_lock(&ioexp_p->lock);
+    len = snprintf(buf_p, 8, "%d\n", get_func(ioexp_p, tobj_p->ioexp_virt_offset));
+    mutex_unlock(&ioexp_p->lock);
+    return len;
+}
+
+
+static ssize_t
+show_attr_present(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_present,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_tx_fault(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_tx_fault,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_rxlos(struct device *dev_p,
+                struct device_attribute *attr_p,
+                char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_rxlos,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_tx_disable(struct device *dev_p,
+                     struct device_attribute *attr_p,
+                     char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_tx_disable,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_reset(struct device *dev_p,
+                struct device_attribute *attr_p,
+                char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_reset,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_lpmod(struct device *dev_p,
+                struct device_attribute *attr_p,
+                char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_lpmod,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_modsel(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_modsel,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_hard_rs0(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_hard_rs0,
+                                   buf_p);
+}
+
+
+static ssize_t
+show_attr_hard_rs1(struct device *dev_p,
+                   struct device_attribute *attr_p,
+                   char *buf_p){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p){
+        return -ENODEV;
+    }
+    return _show_ioexp_binary_attr(tobj_p,
+                                   tobj_p->ioexp_obj_p->get_hard_rs1,
+                                   buf_p);
+}
+
+
+/* ========== Store functions: For I/O Expander (R/W) attribute ==========
+ */
+static ssize_t
+_store_ioexp_binary_attr(struct transvr_obj_s *tobj_p,
+                         int (*set_func)(struct ioexp_obj_s *ioexp_p,
+                                         int virt_offset, int input_val),
+                         const char *buf_p,
+                         size_t count) {
+
+    int input, err;
+    struct ioexp_obj_s *ioexp_p = tobj_p->ioexp_obj_p;
+
+    if (!ioexp_p) {
+        SWPS_ERR("%s: data corruption! <port>:%s\n",
+                 __func__, tobj_p->swp_name);
+        return -ENODATA;
+    }
+    input = sscanf_2_binary(buf_p);
+    if (input < 0) {
+        return -EBFONT;
+    }
+    mutex_lock(&ioexp_p->lock);
+    err = set_func(ioexp_p, tobj_p->ioexp_virt_offset, input);
+    mutex_unlock(&ioexp_p->lock);
+    if (err < 0){
+        return err;
+    }
+    return count;
+}
+
+static ssize_t
+store_attr_tx_disable(struct device *dev_p,
+                      struct device_attribute *attr_p,
+                      const char *buf_p,
+                      size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p) {
+        return -ENODEV;
+    }
+    return _store_ioexp_binary_attr(tobj_p,
+                                    tobj_p->ioexp_obj_p->set_tx_disable,
+                                    buf_p,
+                                    count);
+}
+
+
+static ssize_t
+store_attr_reset(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 const char *buf_p,
+                 size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p) {
+        return -ENODEV;
+    }
+    return _store_ioexp_binary_attr(tobj_p,
+                                    tobj_p->ioexp_obj_p->set_reset,
+                                    buf_p,
+                                    count);
+}
+
+
+static ssize_t
+store_attr_lpmod(struct device *dev_p,
+                 struct device_attribute *attr_p,
+                 const char *buf_p,
+                 size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p) {
+        return -ENODEV;
+    }
+    return _store_ioexp_binary_attr(tobj_p,
+                                    tobj_p->ioexp_obj_p->set_lpmod,
+                                    buf_p,
+                                    count);
+}
+
+
+static ssize_t
+store_attr_modsel(struct device *dev_p,
+                  struct device_attribute *attr_p,
+                  const char *buf_p,
+                  size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p) {
+        return -ENODEV;
+    }
+    return _store_ioexp_binary_attr(tobj_p,
+                                    tobj_p->ioexp_obj_p->set_modsel,
+                                    buf_p,
+                                    count);
+}
+
+
+static ssize_t
+store_attr_hard_rs0(struct device *dev_p,
+                    struct device_attribute *attr_p,
+                    const char *buf_p,
+                    size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p) {
+        return -ENODEV;
+    }
+    return _store_ioexp_binary_attr(tobj_p,
+                                    tobj_p->ioexp_obj_p->set_hard_rs0,
+                                    buf_p,
+                                    count);
+}
+
+
+static ssize_t
+store_attr_hard_rs1(struct device *dev_p,
+                    struct device_attribute *attr_p,
+                    const char *buf_p,
+                    size_t count){
+
+    struct transvr_obj_s *tobj_p = dev_get_drvdata(dev_p);
+    if (!tobj_p) {
+        return -ENODEV;
+    }
+    return _store_ioexp_binary_attr(tobj_p,
+                                    tobj_p->ioexp_obj_p->set_hard_rs1,
+                                    buf_p,
+                                    count);
+}
+
+
+/* ========== SWPS attribute: For module control ==========
+ */
+static DEVICE_ATTR(platform,        S_IRUGO,         show_attr_platform,        NULL);
+static DEVICE_ATTR(version,         S_IRUGO,         show_attr_version,         NULL);
+static DEVICE_ATTR(status,          S_IRUGO,         show_attr_status,          NULL);
+static DEVICE_ATTR(reset_i2c,       S_IWUSR,         NULL,                      store_attr_reset_i2c);
+static DEVICE_ATTR(reset_swps,      S_IWUSR,         NULL,                      store_attr_reset_swps);
+static DEVICE_ATTR(auto_config,     S_IRUGO|S_IWUSR, show_attr_auto_config,     store_attr_auto_config);
+
+/* ========== Transceiver attribute: from eeprom ==========
+ */
+static DEVICE_ATTR(id,              S_IRUGO,         show_attr_id,              NULL);
+static DEVICE_ATTR(ext_id,          S_IRUGO,         show_attr_ext_id,          NULL);
+static DEVICE_ATTR(connector,       S_IRUGO,         show_attr_connector,       NULL);
+static DEVICE_ATTR(vendor_name,     S_IRUGO,         show_attr_vendor_name,     NULL);
+static DEVICE_ATTR(vendor_pn,       S_IRUGO,         show_attr_vendor_pn,       NULL);
+static DEVICE_ATTR(vendor_rev,      S_IRUGO,         show_attr_vendor_rev,      NULL);
+static DEVICE_ATTR(vendor_sn,       S_IRUGO,         show_attr_vendor_sn,       NULL);
+static DEVICE_ATTR(power_cls,       S_IRUGO,         show_attr_power_cls,       NULL);
+static DEVICE_ATTR(br,              S_IRUGO,         show_attr_br,              NULL);
+static DEVICE_ATTR(len_sm,          S_IRUGO,         show_attr_len_sm,          NULL);
+static DEVICE_ATTR(len_smf,         S_IRUGO,         show_attr_len_smf,         NULL);
+static DEVICE_ATTR(len_om1,         S_IRUGO,         show_attr_len_om1,         NULL);
+static DEVICE_ATTR(len_om2,         S_IRUGO,         show_attr_len_om2,         NULL);
+static DEVICE_ATTR(len_om3,         S_IRUGO,         show_attr_len_om3,         NULL);
+static DEVICE_ATTR(len_om4,         S_IRUGO,         show_attr_len_om4,         NULL);
+static DEVICE_ATTR(comp_rev,        S_IRUGO,         show_attr_comp_rev,        NULL);
+static DEVICE_ATTR(comp_eth,        S_IRUGO,         show_attr_comp_eth,        NULL);
+static DEVICE_ATTR(comp_eth_10,     S_IRUGO,         show_attr_comp_eth_10,     NULL);
+static DEVICE_ATTR(comp_eth_10_40,  S_IRUGO,         show_attr_comp_eth_10_40,  NULL);
+static DEVICE_ATTR(comp_extend,     S_IRUGO,         show_attr_comp_extend,     NULL);
+static DEVICE_ATTR(rate_id,         S_IRUGO,         show_attr_rate_id,         NULL);
+static DEVICE_ATTR(temperature,     S_IRUGO,         show_attr_temperature,     NULL);
+static DEVICE_ATTR(voltage,         S_IRUGO,         show_attr_voltage,         NULL);
+static DEVICE_ATTR(tx_bias,         S_IRUGO,         show_attr_tx_bias,         NULL);
+static DEVICE_ATTR(tx_power,        S_IRUGO,         show_attr_tx_power,        NULL);
+static DEVICE_ATTR(rx_power,        S_IRUGO,         show_attr_rx_power,        NULL);
+static DEVICE_ATTR(info,            S_IRUGO,         show_attr_info,            NULL);
+static DEVICE_ATTR(if_type,         S_IRUGO,         show_attr_if_type,         NULL);
+static DEVICE_ATTR(if_speed,        S_IRUGO,         show_attr_if_speed,        NULL);
+static DEVICE_ATTR(if_lane,         S_IRUGO,         show_attr_if_lane,         NULL);
+static DEVICE_ATTR(soft_rx_los,     S_IRUGO,         show_attr_soft_rx_los,     NULL);
+static DEVICE_ATTR(soft_tx_fault,   S_IRUGO,         show_attr_soft_tx_fault,   NULL);
+static DEVICE_ATTR(wavelength,      S_IRUGO,         show_attr_wavelength,      NULL);
+static DEVICE_ATTR(tx_eq,           S_IRUGO|S_IWUSR, show_attr_tx_eq,           store_attr_tx_eq);
+static DEVICE_ATTR(rx_am,           S_IRUGO|S_IWUSR, show_attr_rx_am,           store_attr_rx_am);
+static DEVICE_ATTR(rx_em,           S_IRUGO|S_IWUSR, show_attr_rx_em,           store_attr_rx_em);
+static DEVICE_ATTR(cdr,             S_IRUGO|S_IWUSR, show_attr_cdr,             store_attr_cdr);
+static DEVICE_ATTR(soft_rs0,        S_IRUGO|S_IWUSR, show_attr_soft_rs0,        store_attr_soft_rs0);
+static DEVICE_ATTR(soft_rs1,        S_IRUGO|S_IWUSR, show_attr_soft_rs1,        store_attr_soft_rs1);
+static DEVICE_ATTR(soft_tx_disable, S_IRUGO|S_IWUSR, show_attr_soft_tx_disable, store_attr_soft_tx_disable);
+static DEVICE_ATTR(auto_tx_disable, S_IRUGO|S_IWUSR, show_attr_auto_tx_disable, store_attr_auto_tx_disable);
+static DEVICE_ATTR(extphy_offset,   S_IRUGO|S_IWUSR, show_attr_extphy_offset,   store_attr_extphy_offset);
+static DEVICE_ATTR(extphy_reg,      S_IRUGO|S_IWUSR, show_attr_extphy_reg,      store_attr_extphy_reg);
+
+/* ========== IO Expander attribute: from expander ==========
+ */
+static DEVICE_ATTR(present,         S_IRUGO,         show_attr_present,         NULL);
+static DEVICE_ATTR(tx_fault,        S_IRUGO,         show_attr_tx_fault,        NULL);
+static DEVICE_ATTR(rxlos,           S_IRUGO,         show_attr_rxlos,           NULL);
+static DEVICE_ATTR(tx_disable,      S_IRUGO|S_IWUSR, show_attr_tx_disable,      store_attr_tx_disable);
+static DEVICE_ATTR(reset,           S_IRUGO|S_IWUSR, show_attr_reset,           store_attr_reset);
+static DEVICE_ATTR(lpmod,           S_IRUGO|S_IWUSR, show_attr_lpmod,           store_attr_lpmod);
+static DEVICE_ATTR(modsel,          S_IRUGO|S_IWUSR, show_attr_modsel,          store_attr_modsel);
+static DEVICE_ATTR(hard_rs0,        S_IRUGO|S_IWUSR, show_attr_hard_rs0,        store_attr_hard_rs0);
+static DEVICE_ATTR(hard_rs1,        S_IRUGO|S_IWUSR, show_attr_hard_rs1,        store_attr_hard_rs1);
+
+/* ========== Functions for module handling ==========
+ */
+static void
+clean_port_obj(void){
+
+    dev_t dev_num;
+    char dev_name[32];
+    struct device *device_p;
+    struct transvr_obj_s *transvr_obj_p;
+    int minor_curr, port_id;
+
+    for (minor_curr=0; minor_curr<port_total; minor_curr++){
+        port_id = port_layout[minor_curr].port_id;
+        memset(dev_name, 0, sizeof(dev_name));
+        snprintf(dev_name, sizeof(dev_name), "%s%d", SWP_DEV_PORT, port_id);
+        device_p = get_swpdev_by_name(dev_name);
+        if (!device_p){
+            continue;
+        }
+        transvr_obj_p = dev_get_drvdata(device_p);
+        if (transvr_obj_p){
+            kfree(transvr_obj_p->i2c_client_p);
+            kfree(transvr_obj_p->vendor_name);
+            kfree(transvr_obj_p->vendor_pn);
+            kfree(transvr_obj_p->vendor_rev);
+            kfree(transvr_obj_p->vendor_sn);
+            kfree(transvr_obj_p->worker_p);
+            kfree(transvr_obj_p);
+        }
+        dev_num = MKDEV(port_major, minor_curr);
+        device_unregister(device_p);
+        device_destroy(swp_class_p, dev_num);
+    }
+    SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+static void
+clean_swps_common(void){
+
+    dev_t dev_num;
+    struct device *device_p;
+
+    device_p = get_swpdev_by_name(SWP_DEV_MODCTL);
+    if (device_p){
+        dev_num = MKDEV(ctl_major, 1);
+        device_unregister(device_p);
+        device_destroy(swp_class_p, dev_num);
+    }
+    cancel_delayed_work_sync(&swp_polling);
+    SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+static int
+get_platform_type(void){
+
+    int i;
+    int pf_total = ARRAY_SIZE(platform_map);
+    char log_msg[64] = "ERROR";
+
+    platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL);
+    if (!platform_p){
+        snprintf(log_msg, sizeof(log_msg), "kzalloc fail");
+        goto err_get_platform_type_1;
+    }
+    memset(platform_p->name, 0, sizeof(platform_p->name));
+
+    switch (PLATFORM_SETTINGS) {
+        case PLATFORM_TYPE_AUTO:
+            snprintf(platform_p->name, (sizeof(platform_p->name) - 1),
+                    "%s", dmi_get_system_info(DMI_BOARD_NAME));
+            for (i=0; i<pf_total; i++) {
+                if (strcmp(platform_p->name, platform_map[i].name) == 0) {
+                    platform_p->id = platform_map[i].id;
+                    snprintf(log_msg, sizeof(log_msg),
+                            "Auto detect platform: %d (%s)",
+                            platform_p->id, platform_p->name);
+                    goto ok_get_platform_type_1;
+                }
+            }
+            snprintf(log_msg, sizeof(log_msg),
+                    "Auto detect fail! detect platform: %s",
+                    platform_p->name);
+            goto err_get_platform_type_2;
+
+        case PLATFORM_TYPE_MAGNOLIA:
+        case PLATFORM_TYPE_MAGNOLIA_FNC:
+        case PLATFORM_TYPE_REDWOOD:
+        case PLATFORM_TYPE_REDWOOD_FSL:
+        case PLATFORM_TYPE_HUDSON32I_GA:
+        case PLATFORM_TYPE_SPRUCE:
+        case PLATFORM_TYPE_CYPRESS_GA1:
+        case PLATFORM_TYPE_CYPRESS_GA2:
+        case PLATFORM_TYPE_CYPRESS_BAI:
+        case PLATFORM_TYPE_TAHOE:
+        case PLATFORM_TYPE_SEQUOIA_GA:
+        case PLATFORM_TYPE_LAVENDER_GA:
+        case PLATFORM_TYPE_LAVENDER_ONL:
+        case PLATFORM_TYPE_COTTONWOOD_RANGELEY:
+        case PLATFORM_TYPE_MAPLE:
+            platform_p->id = PLATFORM_SETTINGS;
+            for (i=0; i<pf_total; i++) {
+                if (PLATFORM_SETTINGS == platform_map[i].id) {
+                    snprintf(platform_p->name, (sizeof(platform_p->name) - 1),
+                            "%s", platform_map[i].name);
+                    snprintf(log_msg, sizeof(log_msg),
+                            "User setup platform: %d (%s)",
+                            platform_p->id, platform_p->name);
+                    goto ok_get_platform_type_1;
+                }
+            }
+            snprintf(log_msg, sizeof(log_msg),
+                    "Internal error, can not map id:%d",
+                    PLATFORM_SETTINGS);
+            goto err_get_platform_type_2;
+
+        default:
+            break;
+    }
+    snprintf(log_msg, sizeof(log_msg),
+            "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS);
+    goto err_get_platform_type_2;
+
+ok_get_platform_type_1:
+    SWPS_DEBUG("%s: %s, <conf>:%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+    return 0;
+
+err_get_platform_type_2:
+    kfree(platform_p);
+err_get_platform_type_1:
+    SWPS_ERR("%s: %s <conf>:%d\n", __func__, log_msg, PLATFORM_SETTINGS);
+    return -1;
+}
+
+
+static int
+get_layout_info(void){
+
+    switch (platform_p->id) {
+#ifdef SWPS_MAGNOLIA
+        case PLATFORM_TYPE_MAGNOLIA:
+        case PLATFORM_TYPE_MAGNOLIA_FNC:
+            gpio_rest_mux = magnolia_gpio_rest_mux;
+            ioexp_layout  = magnolia_ioexp_layout;
+            port_layout   = magnolia_port_layout;
+            ioexp_total   = ARRAY_SIZE(magnolia_ioexp_layout);
+            port_total    = ARRAY_SIZE(magnolia_port_layout);
+            break;
+#endif
+#ifdef SWPS_REDWOOD
+        case PLATFORM_TYPE_REDWOOD:
+            gpio_rest_mux = redwood_gpio_rest_mux;
+            ioexp_layout  = redwood_ioexp_layout;
+            port_layout   = redwood_port_layout;
+            ioexp_total   = ARRAY_SIZE(redwood_ioexp_layout);
+            port_total    = ARRAY_SIZE(redwood_port_layout);
+            break;
+#endif
+#ifdef SWPS_HUDSON32I_GA
+        case PLATFORM_TYPE_HUDSON32I_GA:
+            gpio_rest_mux = hudsin32iga_gpio_rest_mux;
+            ioexp_layout  = hudson32iga_ioexp_layout;
+            port_layout   = hudson32iga_port_layout;
+            ioexp_total   = ARRAY_SIZE(hudson32iga_ioexp_layout);
+            port_total    = ARRAY_SIZE(hudson32iga_port_layout);
+            break;
+#endif
+#ifdef SWPS_SPRUCE
+        case PLATFORM_TYPE_SPRUCE:
+            gpio_rest_mux = spruce_gpio_rest_mux;
+            ioexp_layout  = spruce_ioexp_layout;
+            port_layout   = spruce_port_layout;
+            ioexp_total   = ARRAY_SIZE(spruce_ioexp_layout);
+            port_total    = ARRAY_SIZE(spruce_port_layout);
+            break;
+#endif
+#ifdef SWPS_CYPRESS_GA1
+        case PLATFORM_TYPE_CYPRESS_GA1:
+            gpio_rest_mux = cypress_ga1_gpio_rest_mux;
+            ioexp_layout  = cypress_ga1_ioexp_layout;
+            port_layout   = cypress_ga1_port_layout;
+            ioexp_total   = ARRAY_SIZE(cypress_ga1_ioexp_layout);
+            port_total    = ARRAY_SIZE(cypress_ga1_port_layout);
+            break;
+#endif
+#ifdef SWPS_CYPRESS_GA2
+        case PLATFORM_TYPE_CYPRESS_GA2:
+            gpio_rest_mux = cypress_ga2_gpio_rest_mux;
+            ioexp_layout  = cypress_ga2_ioexp_layout;
+            port_layout   = cypress_ga2_port_layout;
+            ioexp_total   = ARRAY_SIZE(cypress_ga2_ioexp_layout);
+            port_total    = ARRAY_SIZE(cypress_ga2_port_layout);
+            break;
+#endif
+#ifdef SWPS_CYPRESS_BAI
+        case PLATFORM_TYPE_CYPRESS_BAI:
+            gpio_rest_mux = cypress_b_gpio_rest_mux;
+            ioexp_layout  = cypress_b_ioexp_layout;
+            port_layout   = cypress_b_port_layout;
+            ioexp_total   = ARRAY_SIZE(cypress_b_ioexp_layout);
+            port_total    = ARRAY_SIZE(cypress_b_port_layout);
+            break;
+#endif
+#ifdef SWPS_REDWOOD_FSL
+        case PLATFORM_TYPE_REDWOOD_FSL:
+            gpio_rest_mux = redwood_fsl_gpio_rest_mux;
+            ioexp_layout  = redwood_fsl_ioexp_layout;
+            port_layout   = redwood_fsl_port_layout;
+            ioexp_total   = ARRAY_SIZE(redwood_fsl_ioexp_layout);
+            port_total    = ARRAY_SIZE(redwood_fsl_port_layout);
+            break;
+#endif
+#ifdef SWPS_TAHOE
+        case PLATFORM_TYPE_TAHOE:
+            gpio_rest_mux = tahoe_gpio_rest_mux;
+            ioexp_layout  = tahoe_ioexp_layout;
+            port_layout   = tahoe_port_layout;
+            ioexp_total   = ARRAY_SIZE(tahoe_ioexp_layout);
+            port_total    = ARRAY_SIZE(tahoe_port_layout);
+            break;
+#endif
+#ifdef SWPS_SEQUOIA
+        case PLATFORM_TYPE_SEQUOIA_GA:
+            gpio_rest_mux = sequoia_gpio_rest_mux;
+            ioexp_layout  = sequoia_ioexp_layout;
+            port_layout   = sequoia_port_layout;
+            ioexp_total   = ARRAY_SIZE(sequoia_ioexp_layout);
+            port_total    = ARRAY_SIZE(sequoia_port_layout);
+            break;
+#endif
+#ifdef SWPS_LAVENDER
+        case PLATFORM_TYPE_LAVENDER_GA:
+        case PLATFORM_TYPE_LAVENDER_ONL:
+            gpio_rest_mux = lavender_gpio_rest_mux;
+            ioexp_layout  = lavender_ioexp_layout;
+            port_layout   = lavender_port_layout;
+            ioexp_total   = ARRAY_SIZE(lavender_ioexp_layout);
+            port_total    = ARRAY_SIZE(lavender_port_layout);
+            break;
+#endif
+#ifdef SWPS_COTTONWOOD_RANGELEY
+        case PLATFORM_TYPE_COTTONWOOD_RANGELEY:
+            gpio_rest_mux = cottonwood_rangeley_gpio_rest_mux;
+            ioexp_layout  = cottonwood_rangeley_ioexp_layout;
+            port_layout   = cottonwood_rangeley_port_layout;
+            ioexp_total   = ARRAY_SIZE(cottonwood_rangeley_ioexp_layout);
+            port_total    = ARRAY_SIZE(cottonwood_rangeley_port_layout);
+            break;
+#endif
+#ifdef SWPS_MAPLE
+        case PLATFORM_TYPE_MAPLE:
+            gpio_rest_mux = maple_gpio_rest_mux;
+            ioexp_layout  = maple_ioexp_layout;
+            port_layout   = maple_port_layout;
+            ioexp_total   = ARRAY_SIZE(maple_ioexp_layout);
+            port_total    = ARRAY_SIZE(maple_port_layout);
+            break;
+#endif
+        default:
+            SWPS_ERR(" Invalid platform: %d (%s)\n",
+                    platform_p->id, platform_p->name);
+            return -1;
+    }
+    SWPS_INFO("Start to initial platform: %d (%s)\n",
+              platform_p->id, platform_p->name);
+    return 0;
+}
+
+
+/* ========== Functions for objects operations ==========
+ */
+static int
+__detect_issues_port(int minor_num) {
+
+    struct transvr_obj_s *tobj_p;
+    int  port_id = port_layout[minor_num].port_id;
+    char port_name[32] = "ERR";
+    char *i2c_emsg = "detected bad transceiver/cable";
+
+    memset(port_name, 0, sizeof(port_name));
+    snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id);
+    tobj_p = _get_transvr_obj(port_name);
+    if (!tobj_p) {
+        SWPS_INFO("%s: tobj_p is NULL <minor>:%d\n", __func__, minor_num);
+        return -1;
+    }
+    if (resync_channel_tier_2(tobj_p) < 0) {
+        if (check_channel_tier_1() < 0) {
+            alarm_msg_2_user(tobj_p, i2c_emsg);
+            return -2;;
+        }
+    }
+    return 0;
+}
+
+
+static int
+_detect_issues_port(void) {
+    /* OK  : retrun -1;
+     * Fail: return fail at which minor number (0~N)
+     */
+    char *emsg = "ERR";
+    int  minor = 0;
+    int  minor_2st = 1;
+
+    /* Force moving the initial channel pointer
+     * Filter out case of fail at minor-0 port
+     */
+    while (minor_2st < port_total) {
+        minor = minor_2st;
+        if (__detect_issues_port(minor_2st) < 0) {
+            emsg = "detect minor_2st fail";
+            goto err_p_detect_issues_port;
+        }
+        minor_2st += 8;
+    }
+    /* Scan all port */
+    for (minor=0; minor<port_total; minor++) {
+        if (__detect_issues_port(minor) < 0) {
+            emsg = "is I2C issues port";
+            goto err_p_detect_issues_port;
+        }
+    }
+    return -1;
+
+err_p_detect_issues_port:
+    SWPS_DEBUG("%s: minor:%d %s\n", __func__, minor, emsg);
+    return minor;
+}
+
+
+static int
+_isolate_issues_port(int minor_num) {
+
+    struct transvr_obj_s *tobj_p;
+    char port_name[32];
+    int  port_id = port_layout[minor_num].port_id;
+
+    memset(port_name, 0, sizeof(port_name));
+    snprintf(port_name, sizeof(port_name), "%s%d", SWP_DEV_PORT, port_id);
+    tobj_p = _get_transvr_obj(port_name);
+    if (!tobj_p) {
+        return -1;
+    }
+    return isolate_transvr_obj(tobj_p);
+}
+
+
+static int
+_reset_i2c_topology_tier_1(void) {
+
+    if (reset_mux_gpio() < 0) {
+        SWPS_ERR("%s: reset MUX GPIO fail!\n", __func__);
+        return -1;
+    }
+    SWPS_DEBUG("%s: reset_mux_gpio OK.\n", __func__);
+    if (resync_channel_tier_1() < 0) {
+        SWPS_ERR("%s: resync tier-1 channel fail!\n", __func__);
+        return -1;
+    }
+    SWPS_DEBUG("%s: resync_channel_tier_1 OK.\n", __func__);
+    return 0;
+}
+
+
+static int
+reset_i2c_topology(void) {
+
+    int run_count = 0;
+    int minor_err = 0;
+    char *emsg = "ERR";
+
+    /* Get all lock */
+    if (lock_ioexp_all() < 0) {
+        emsg = "lock_ioexp_all fail";
+        goto err_reset_i2c_topology_1;
+    }
+    if (lock_tobj_all() < 0) {
+        emsg = "lock_tobj_all fail";
+        goto err_reset_i2c_topology_2;
+    }
+    SWPS_DEBUG("%s: get Lock OK.\n", __func__);
+    /* Reset tier-1 topology */
+    if (_reset_i2c_topology_tier_1() < 0) {
+        emsg = "initial task fail";
+        goto err_reset_i2c_topology_3;
+    }
+    SWPS_DEBUG("%s: reset tier-1 OK.\n", __func__);
+    /* Reset tier-2 topology */
+    for (run_count=0; run_count<port_total; run_count++) {
+        SWPS_DEBUG("%s: reset tier-2 No.%d-run go.\n", __func__, run_count);
+        minor_err = _detect_issues_port();
+        /* Case: no issues port */
+        if (minor_err < 0) {
+            break;
+        }
+        /* Case: has issues port */
+        if (_isolate_issues_port(minor_err) < 0) {
+            emsg = "isolate fail";
+            goto err_reset_i2c_topology_3;
+        }
+        if (_reset_i2c_topology_tier_1() < 0) {
+            emsg = "reset tier-1 fail";
+            goto err_reset_i2c_topology_3;
+        }
+    }
+    unlock_tobj_all();
+    unlock_ioexp_all();
+    flag_mod_state = SWP_STATE_NORMAL;
+    SWPS_INFO("%s: done\n", __func__);
+    return 0;
+
+err_reset_i2c_topology_3:
+    unlock_tobj_all();
+err_reset_i2c_topology_2:
+    unlock_ioexp_all();
+err_reset_i2c_topology_1:
+    flag_mod_state = SWP_STATE_I2C_DIE;
+    SWPS_INFO("%s: %s <minor>:%d\n", __func__, emsg, minor_err);
+    return -1;
+}
+
+
+static int
+check_transvr_obj_one(char *dev_name){
+    /* [Return]
+     *    0 : Doesn't need to take care
+     *   -1 : Single error
+     *   -2 : Critical error (I2C topology die)
+     *   -9 : Internal error
+     */
+    struct transvr_obj_s *tobj_p = NULL;
+    int retval = -9;
+
+    tobj_p = _get_transvr_obj(dev_name);
+    if (!tobj_p) {
+        SWPS_ERR("%s: %s _get_transvr_obj fail\n",
+                __func__, dev_name);
+        return -9;
+    }
+    /* Check transceiver current status */
+    lock_transvr_obj(tobj_p);
+    retval = tobj_p->check(tobj_p);
+    unlock_transvr_obj(tobj_p);
+    switch (retval) {
+        case 0:
+        case ERR_TRANSVR_UNPLUGGED:
+        case ERR_TRNASVR_BE_ISOLATED:
+        case ERR_TRANSVR_TASK_BUSY:
+            return 0;
+
+        case ERR_TRANSVR_I2C_CRASH:
+        default:
+            break;
+    }
+    /* Identify abnormal case */
+    if (check_channel_tier_1() < 0) {
+        SWPS_DEBUG("%s: %s critical error <err>:%d\n",
+                   __func__, dev_name, retval);
+        return -2;
+    }
+    SWPS_DEBUG("%s: %s single error <err>:%d\n",
+               __func__, dev_name, retval);
+    return -1;
+}
+
+
+static int
+check_transvr_objs(void){
+
+    char dev_name[32];
+    int port_id, err_code;
+    int minor_curr = 0;
+
+    for (minor_curr=0; minor_curr<port_total; minor_curr++) {
+        /* Generate device name */
+        port_id = port_layout[minor_curr].port_id;
+        memset(dev_name, 0, sizeof(dev_name));
+        snprintf(dev_name, sizeof(dev_name), "%s%d", SWP_DEV_PORT, port_id);
+        /* Handle current status */
+        err_code = check_transvr_obj_one(dev_name);
+        switch (err_code) {
+            case  0:
+            case -1:
+                break;
+
+            case -2:
+                SWPS_DEBUG("%s: %s reset I2C GO.\n",
+                           __func__, dev_name);
+                if (reset_i2c_topology() < 0) {
+                    goto err_check_transvr_objs;
+                }
+                SWPS_DEBUG("%s: %s reset I2C OK.\n",
+                           __func__, dev_name);
+                break;
+
+            case -9:
+            default:
+                SWPS_DEBUG("%s: %s internal error <err>:%d\n",
+                        __func__, dev_name, err_code);
+                break;
+        }
+    }
+    return 0;
+
+err_check_transvr_objs:
+    SWPS_ERR("%s: %s reset_i2c_topology fail.\n",
+               __func__, dev_name);
+    return -1;
+}
+
+
+static void
+swp_polling_worker(struct work_struct *work){
+
+    /* Reset I2C */
+    if (flag_i2c_reset) {
+        goto polling_reset_i2c;
+    }
+    /* Check IOEXP */
+    if (check_ioexp_objs() < 0) {
+        goto polling_reset_i2c;
+    }
+    /* Check transceiver */
+    if (check_transvr_objs() < 0) {
+        SWPS_DEBUG("%s: check_transvr_objs fail.\n", __func__);
+        flag_i2c_reset = 1;
+    }
+    goto polling_schedule_round;
+
+polling_reset_i2c:
+    SWPS_DEBUG("%s: reset_i2c_topology start.\n", __func__);
+    if (reset_i2c_topology() < 0) {
+        SWPS_ERR("%s: reset i2c fail!\n", __func__);
+        flag_i2c_reset = 1;
+    } else {
+        SWPS_DEBUG("%s: reset_i2c_topology OK.\n", __func__);
+        flag_i2c_reset = 0;
+    }
+polling_schedule_round:
+    schedule_delayed_work(&swp_polling, _get_polling_period());
+}
+
+
+/* ========== Functions for register something ==========
+ */
+static int
+register_transvr_common_attr(struct device *device_p){
+
+    char *err_attr = NULL;
+
+    if (device_create_file(device_p, &dev_attr_id) < 0) {
+          err_attr = "dev_attr_id";
+           goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_ext_id) < 0) {
+          err_attr = "dev_attr_ext_id";
+           goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_connector) < 0) {
+          err_attr = "dev_attr_connector";
+           goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_vendor_name) < 0) {
+        err_attr = "dev_attr_vendor_name";
+         goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_vendor_pn) < 0) {
+        err_attr = "dev_attr_vendor_pn";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_vendor_rev) < 0) {
+        err_attr = "dev_attr_vendor_rev";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_vendor_sn) < 0) {
+        err_attr = "dev_attr_vendor_sn";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_br) < 0) {
+        err_attr = "dev_attr_br";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_len_smf) < 0) {
+        err_attr = "dev_attr_len_smf";
+         goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_len_om1) < 0) {
+         err_attr = "dev_attr_len_om1";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_len_om2) < 0) {
+         err_attr = "dev_attr_len_om2";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_len_om3) < 0) {
+         err_attr = "dev_attr_len_om3";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_len_om4) < 0) {
+         err_attr = "dev_attr_len_om4";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_comp_extend) < 0) {
+        err_attr = "dev_attr_comp_extend";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_comp_eth) < 0) {
+        err_attr = "dev_attr_comp_eth";
+         goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_comp_rev) < 0) {
+        err_attr = "dev_attr_comp_rev";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_info) < 0) {
+        err_attr = "dev_attr_info";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_if_type) < 0) {
+        err_attr = "dev_attr_if_type";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_if_speed) < 0) {
+        err_attr = "dev_attr_if_speed";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_if_lane) < 0) {
+        err_attr = "dev_attr_if_lane";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_temperature) < 0) {
+        err_attr = "dev_attr_temperature";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_voltage) < 0) {
+        err_attr = "dev_attr_voltage";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_tx_bias) < 0) {
+        err_attr = "dev_attr_tx_bias";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_tx_power) < 0) {
+        err_attr = "dev_attr_tx_power";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_rx_power) < 0) {
+        err_attr = "dev_attr_rx_power";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_tx_eq) < 0) {
+        err_attr = "dev_attr_tx_eq";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_rx_em) < 0) {
+        err_attr = "dev_attr_rx_em";
+        goto err_transvr_comm_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_wavelength) < 0) {
+        err_attr = "dev_attr_wavelength";
+        goto err_transvr_comm_attr;
+    }
+    return 0;
+
+err_transvr_comm_attr:
+    SWPS_ERR("%s: %s\n", __func__, err_attr);
+    return -1;
+}
+
+static int
+register_transvr_sfp_attr(struct device *device_p){
+
+    char *err_attr = NULL;
+
+    if (register_transvr_common_attr(device_p) < 0) {
+        err_attr = "register_transvr_common_attr";
+        goto err_transvr_sfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_comp_eth_10) < 0) {
+        err_attr = "dev_attr_comp_eth_10";
+         goto err_transvr_sfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_len_sm) < 0) {
+        err_attr = "dev_attr_len_sm";
+         goto err_transvr_sfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_rate_id) < 0) {
+        err_attr = "dev_attr_rate_id";
+        goto err_transvr_sfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_soft_rs0) < 0) {
+        err_attr = "dev_attr_soft_rs0";
+        goto err_transvr_sfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_soft_rs1) < 0) {
+        err_attr = "dev_attr_soft_rs1";
+        goto err_transvr_sfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_extphy_offset) < 0) {
+        err_attr = "dev_attr_extphy_offset";
+        goto err_transvr_sfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_extphy_reg) < 0) {
+        err_attr = "dev_attr_extphy_reg";
+        goto err_transvr_sfp_attr;
+    }
+    return 0;
+
+err_transvr_sfp_attr:
+    SWPS_ERR("%s: %s\n", __func__, err_attr);
+    return -1;
+}
+
+
+static int
+register_transvr_qsfp_attr(struct device *device_p){
+
+    char *err_attr = NULL;
+
+    if (register_transvr_common_attr(device_p) < 0) {
+        err_attr = "register_transvr_common_attr";
+        goto err_transvr_qsfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_comp_eth_10_40) < 0) {
+        err_attr = "dev_attr_comp_eth_10_40";
+        goto err_transvr_qsfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_power_cls) < 0) {
+        err_attr = "dev_attr_power_cls";
+        goto err_transvr_qsfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_soft_rx_los) < 0) {
+        err_attr = "soft_rx_los";
+        goto err_transvr_qsfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_soft_tx_disable) < 0) {
+        err_attr = "soft_tx_disable";
+        goto err_transvr_qsfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_auto_tx_disable) < 0) {
+        err_attr = "auto_tx_disable";
+        goto err_transvr_qsfp_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_soft_tx_fault) < 0) {
+        err_attr = "soft_tx_fault";
+        goto err_transvr_qsfp_attr;
+    }
+    return 0;
+
+err_transvr_qsfp_attr:
+    SWPS_ERR("%s: %s\n", __func__, err_attr);
+    return -1;
+}
+
+
+static int
+register_transvr_qsfp28_attr(struct device *device_p){
+
+    char *err_attr = NULL;
+
+    if (register_transvr_qsfp_attr(device_p) < 0){
+        err_attr = "register_transvr_qsfp_attr";
+        goto err_transvr_qsfp28_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_cdr) < 0) {
+        err_attr = "dev_attr_cdr";
+        goto err_transvr_qsfp28_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_rx_am) < 0) {
+        err_attr = "dev_attr_rx_am";
+        goto err_transvr_qsfp28_attr;
+    }
+    return 0;
+
+err_transvr_qsfp28_attr:
+    SWPS_ERR("%s: %s\n", __func__, err_attr);
+    return -1;
+}
+
+
+static int
+register_transvr_attr(struct device *device_p,
+                      struct transvr_obj_s *transvr_obj){
+
+    switch (transvr_obj->layout){
+        case TRANSVR_TYPE_SFP:
+            if (register_transvr_sfp_attr(device_p) < 0){
+                goto err_reg_tvr_attr;
+            }
+            break;
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+            if (register_transvr_qsfp_attr(device_p) < 0){
+                goto err_reg_tvr_attr;
+            }
+            break;
+        case TRANSVR_TYPE_QSFP_28:
+            if (register_transvr_qsfp28_attr(device_p) < 0){
+                goto err_reg_tvr_attr;
+            }
+            break;
+        default:
+            goto err_reg_tvr_attr;
+    }
+    return 0;
+
+err_reg_tvr_attr:
+    SWPS_ERR("%s: fail! type=%d \n", __func__, transvr_obj->type);
+    return -1;
+}
+
+
+static int
+register_ioexp_attr_sfp_1(struct device *device_p){
+    /* Support machine type:
+     * - SFP : Magnolia
+     */
+    char *err_attr = NULL;
+
+    if (device_create_file(device_p, &dev_attr_present) < 0) {
+           err_attr = "dev_attr_present";
+        goto err_ioexp_sfp1_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_tx_fault) < 0) {
+        err_attr = "dev_attr_tx_fault";
+        goto err_ioexp_sfp1_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_rxlos) < 0) {
+        err_attr = "dev_attr_rxlos";
+        goto err_ioexp_sfp1_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_tx_disable) < 0) {
+        err_attr = "dev_attr_tx_disable";
+         goto err_ioexp_sfp1_attr;
+    }
+    return 0;
+
+err_ioexp_sfp1_attr:
+    SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+    return -1;
+}
+
+
+static int
+register_ioexp_attr_sfp_2(struct device *device_p){
+    /* Support machine type:
+     * - SFP28 : Cypress
+     */
+    char *err_attr = NULL;
+
+    if (register_ioexp_attr_sfp_1(device_p) < 0){
+        goto err_ioexp_sfp2_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_hard_rs0) < 0) {
+        err_attr = "dev_attr_hard_rs0";
+         goto err_ioexp_sfp2_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_hard_rs1) < 0) {
+        err_attr = "dev_attr_hard_rs1";
+         goto err_ioexp_sfp2_attr;
+    }
+    return 0;
+
+err_ioexp_sfp2_attr:
+    SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+    return -1;
+}
+
+
+static int
+register_ioexp_attr_qsfp_1(struct device *device_p){
+    /* Support machine type:
+     * - QSFP  : Magnolia, Redwood, Hudson32i
+     * - QSFP+ : Magnolia, Redwood, Hudson32i
+     * - QSFP28: Redwood
+     */
+    char *err_attr = NULL;
+
+    if (device_create_file(device_p, &dev_attr_present) < 0) {
+           err_attr = "dev_attr_present";
+        goto err_ioexp_qsfp1_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_reset) < 0) {
+           err_attr = "dev_attr_reset";
+        goto err_ioexp_qsfp1_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_lpmod) < 0) {
+        err_attr = "dev_attr_lpmod";
+        goto err_ioexp_qsfp1_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_modsel) < 0) {
+           err_attr = "dev_attr_modsel";
+        goto err_ioexp_qsfp1_attr;
+    }
+    return 0;
+
+err_ioexp_qsfp1_attr:
+    SWPS_ERR("Add device attribute:%s failure! \n",err_attr);
+    return -1;
+}
+
+
+static int
+register_modctl_attr(struct device *device_p){
+
+    char *err_msg = NULL;
+
+    if (device_create_file(device_p, &dev_attr_platform) < 0) {
+        err_msg = "dev_attr_platform";
+        goto err_reg_modctl_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_version) < 0) {
+        err_msg = "dev_attr_version";
+        goto err_reg_modctl_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_status) < 0) {
+        err_msg = "dev_attr_status";
+        goto err_reg_modctl_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_reset_i2c) < 0) {
+        err_msg = "dev_attr_reset_i2c";
+        goto err_reg_modctl_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_reset_swps) < 0) {
+        err_msg = "dev_attr_reset_swps";
+        goto err_reg_modctl_attr;
+    }
+    if (device_create_file(device_p, &dev_attr_auto_config) < 0) {
+        err_msg = "dev_attr_auto_config";
+        goto err_reg_modctl_attr;
+    }
+    return 0;
+
+err_reg_modctl_attr:
+    SWPS_ERR("%s: %s\n", __func__, err_msg);
+    return -1;
+}
+
+
+static int
+register_ioexp_attr(struct device *device_p,
+                  struct transvr_obj_s *transvr_obj){
+
+    char *err_msg = "ERR";
+
+    switch (transvr_obj->ioexp_obj_p->ioexp_type){
+        case IOEXP_TYPE_MAGINOLIA_NAB:
+        case IOEXP_TYPE_MAGINOLIA_4AB:
+        case CPLD_TYPE_COTTONWOOD:
+            if (register_ioexp_attr_sfp_1(device_p) < 0){
+                err_msg = "register_ioexp_attr_sfp_1 fail";
+                goto err_reg_ioexp_attr;
+            }
+            break;
+        case IOEXP_TYPE_CYPRESS_NABC:
+        case IOEXP_TYPE_MAPLE_NABC:
+            if (register_ioexp_attr_sfp_2(device_p) < 0){
+                err_msg = "register_ioexp_attr_sfp_2 fail";
+                goto err_reg_ioexp_attr;
+            }
+            break;
+        case IOEXP_TYPE_MAGINOLIA_7AB:
+        case IOEXP_TYPE_SPRUCE_7AB:
+        case IOEXP_TYPE_CYPRESS_7ABC:
+        case IOEXP_TYPE_REDWOOD_P01P08:
+        case IOEXP_TYPE_REDWOOD_P09P16:
+        case IOEXP_TYPE_HUDSON32IGA_P01P08:
+        case IOEXP_TYPE_HUDSON32IGA_P09P16:
+        case IOEXP_TYPE_TAHOE_5A:
+        case IOEXP_TYPE_TAHOE_6ABC:
+        case IOEXP_TYPE_SEQUOIA_NABC:
+        case IOEXP_TYPE_LAVENDER_P65:
+        case IOEXP_TYPE_MAPLE_0ABC:
+            if (register_ioexp_attr_qsfp_1(device_p) < 0){
+                err_msg = "register_ioexp_attr_qsfp_1 fail";
+                goto err_reg_ioexp_attr;
+            }
+            break;
+
+        default:
+            err_msg = "Unknow type";
+            goto err_reg_ioexp_attr;
+    }
+    return 0;
+
+err_reg_ioexp_attr:
+    SWPS_ERR("%s: %s <type>:%d \n",
+            __func__, err_msg, transvr_obj->ioexp_obj_p->ioexp_type);
+    return -1;
+}
+
+
+static int
+register_modctl_device(void) {
+
+    struct device *device_p = NULL;
+    int minor_comm = 0; /* Default minor number for common device */
+    dev_t dev_num  = MKDEV(ctl_major, minor_comm);
+    char *err_msg  = "ERROR";
+
+    device_p = device_create(swp_class_p,     /* struct class *cls     */
+                             NULL,            /* struct device *parent */
+                             dev_num,         /* dev_t devt            */
+                             NULL,            /* void *private_data    */
+                             SWP_DEV_MODCTL); /* const char *fmt       */
+    if (IS_ERR(device_p)){
+        err_msg = "device_create fail";
+        goto err_register_modctl_device_1;
+    }
+    if (register_modctl_attr(device_p) < 0) {
+        err_msg = "register_modctl_attr fail";
+        goto err_register_modctl_device_2;
+    }
+    return 0;
+
+err_register_modctl_device_2:
+    device_unregister(device_p);
+    device_destroy(swp_class_p, dev_num);
+err_register_modctl_device_1:
+    SWPS_ERR("%s: %s\n", __func__, err_msg);
+    return -1;
+}
+
+
+static int
+register_port_device(char *dev_name,
+                     dev_t dev_num,
+                     struct transvr_obj_s *transvr_obj){
+
+    struct device *device_p = NULL;
+    device_p = device_create(swp_class_p,   /* struct class *cls     */
+                             NULL,          /* struct device *parent */
+                             dev_num,       /* dev_t devt            */
+                             transvr_obj,   /* void *private_data    */
+                             dev_name);     /* const char *fmt       */
+    if (IS_ERR(device_p)){
+        goto err_regswp_create_dev;
+    }
+    if (register_transvr_attr(device_p, transvr_obj) < 0){
+        goto err_regswp_reg_attr;
+    }
+    if (register_ioexp_attr(device_p, transvr_obj) < 0){
+           goto err_regswp_reg_attr;
+    }
+    return 0;
+
+err_regswp_reg_attr:
+    device_unregister(device_p);
+    device_destroy(swp_class_p, dev_num);
+err_regswp_create_dev:
+    SWPS_ERR("%s fail! <port>:%s\n", __func__, dev_name);
+    return -1;
+}
+
+
+static int
+register_swp_module(void){
+
+    dev_t ctl_devt  = 0;
+    dev_t port_devt = 0;
+    int dev_total = port_total + 1; /* char_dev for module control */
+
+    /* Register device number */
+    if (alloc_chrdev_region(&ctl_devt, 0, 1, SWP_DEV_MODCTL) < 0){
+        SWPS_WARN("Allocate CTL MAJOR failure! \n");
+        goto err_register_swp_module_1;
+    }
+    if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){
+        SWPS_WARN("Allocate PORT MAJOR failure! \n");
+        goto err_register_swp_module_2;
+    }
+    ctl_major  = MAJOR(ctl_devt);
+    port_major = MAJOR(port_devt);
+
+    /* Create class object */
+    swp_class_p = class_create(THIS_MODULE, SWP_CLS_NAME);
+    if (IS_ERR(swp_class_p)) {
+        SWPS_ERR("Create class failure! \n");
+        goto err_register_swp_module_3;
+    }
+    return 0;
+
+err_register_swp_module_3:
+    unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+err_register_swp_module_2:
+    unregister_chrdev_region(MKDEV(ctl_major, 0), 1);
+err_register_swp_module_1:
+    return -1;
+}
+
+
+/* ========== Module initial relate ==========
+ */
+static int
+create_ioexp_objs(void) {
+
+    int i, run_mod;
+
+    /* Clean IOEXP object */
+    clean_ioexp_objs();
+    /* Get running mode */
+    run_mod = IOEXP_MODE_DIRECT;
+    if (SWP_POLLING_ENABLE){
+        run_mod = IOEXP_MODE_POLLING;
+    }
+    /* Create IOEXP object */
+    for(i=0; i<ioexp_total; i++){
+        if (create_ioexp_obj(ioexp_layout[i].ioexp_id,
+                             ioexp_layout[i].ioexp_type,
+                             (ioexp_layout[i].addr),
+                             run_mod) < 0) {
+            goto err_initioexp_create_obj_1;
+        }
+    }
+    return 0;
+
+err_initioexp_create_obj_1:
+    clean_ioexp_objs();
+    return -1;
+}
+
+
+static int
+create_port_objs(void) {
+
+    int port_id, chan_id, ioexp_id, ioexp_virt_offset;
+    int transvr_type, chipset_type, run_mod, i, j;
+    int minor_curr = 0;
+    int ok_count   = 0;
+    int devlen_max = 31; // 32 - 1
+    char dev_name[32] = "ERROR";
+    char err_msg[64]  = "ERROR";
+    struct transvr_obj_s* transvr_obj_p = NULL;
+    struct ioexp_obj_s *ioexp_obj_p = NULL;
+    struct device *dev_p = NULL;
+
+    for (minor_curr=0; minor_curr<port_total; minor_curr++) {
+        /* Get info from  port_layout[] */
+        port_id           = port_layout[minor_curr].port_id;
+        chan_id           = port_layout[minor_curr].chan_id;
+        ioexp_id          = port_layout[minor_curr].ioexp_id;
+        ioexp_virt_offset = port_layout[minor_curr].ioexp_offset;
+        transvr_type      = port_layout[minor_curr].transvr_type;
+        chipset_type      = port_layout[minor_curr].chipset_type;
+        /* Get running mode */
+        run_mod = TRANSVR_MODE_DIRECT;
+        if (SWP_POLLING_ENABLE){
+            run_mod = TRANSVR_MODE_POLLING;
+        }
+        /* Prepare device name */
+        if (strlen(SWP_DEV_PORT) > devlen_max) {
+            snprintf(err_msg, sizeof(err_msg),
+                    "SWP_DEV_PORT too long!");
+            goto err_initport_create_tranobj;
+        }
+        memset(dev_name, 0, sizeof(dev_name));
+        snprintf(dev_name, devlen_max, "%s%d", SWP_DEV_PORT, port_id);
+        /* Create transceiver object */
+        ioexp_obj_p = get_ioexp_obj(ioexp_id);
+        if (!ioexp_obj_p){
+            snprintf(err_msg, sizeof(err_msg),
+                    "IOEXP object:%d not exist", ioexp_id);
+            goto err_initport_create_tranobj;
+        }
+        transvr_obj_p = create_transvr_obj(dev_name, chan_id, ioexp_obj_p,
+                                           ioexp_virt_offset, transvr_type,
+                                           chipset_type, run_mod);
+        if (!transvr_obj_p){
+            snprintf(err_msg, sizeof(err_msg),
+                    "Create transceiver object fail <id>:%s", dev_name);
+            goto err_initport_create_tranobj;
+        }
+        /* Setup Lane_ID mapping */
+        i = ARRAY_SIZE(port_layout[minor_curr].lane_id);
+        j = ARRAY_SIZE(transvr_obj_p->lane_id);
+        if (i != j) {
+            snprintf(err_msg, sizeof(err_msg),
+                    "Lane_id size inconsistent %d/%d", i, j);
+            goto err_initport_reg_device;
+        }
+        memcpy(transvr_obj_p->lane_id, port_layout[minor_curr].lane_id, i*sizeof(int));
+        /* Create and register device object */
+        if (register_port_device(dev_name, MKDEV(port_major, minor_curr), transvr_obj_p) < 0){
+            snprintf(err_msg, sizeof(err_msg),
+                    "register_port_device fail");
+            goto err_initport_reg_device;
+        }
+        /* Setup device_ptr of transvr_obj */
+        dev_p = get_swpdev_by_name(dev_name);
+        if (!dev_p){
+            snprintf(err_msg, sizeof(err_msg),
+                    "get_swpdev_by_name fail");
+            goto err_initport_reg_device;
+        }
+        transvr_obj_p->transvr_dev_p = dev_p;
+        /* Success */
+        ok_count++;
+    }
+    SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count);
+    return 0;
+
+err_initport_reg_device:
+    kfree(transvr_obj_p);
+err_initport_create_tranobj:
+    clean_port_obj();
+    SWPS_ERR("%s: %s", __func__, err_msg);
+    SWPS_ERR("Dump: <port_id>:%d <chan_id>:%d <ioexp_id>:%d <voffset>:%d <tvr_type>:%d <run_mod>:%d\n",
+            port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod);
+    return -1;
+}
+
+
+static int
+init_dev_topology(void){
+
+    int err;
+    char *emsg = "ERR";
+    flag_mod_state = SWP_STATE_NORMAL;
+
+    err = init_ioexp_objs();
+    switch(err){
+        case 0:  /* Normal */
+            SWPS_DEBUG("%s: normal case\n", __func__);
+            break;
+
+        case -1: /* topology error */
+            SWPS_DEBUG("%s: detect tier-1 topology initial failure <err>:%d\n",
+                       __func__, err);
+            /* Reset and isolate */
+            err = reset_i2c_topology();
+            if (err < 0) {
+                emsg = "reset i2c topology fail";
+                goto err_init_dev_topology;
+            }
+            /* Re-initial again */
+            err = init_ioexp_objs();
+            if (err < 0) {
+                emsg = "re-init ioexp objects fail";
+                goto err_init_dev_topology;
+            }
+            break;
+
+        case -2: /* Internal error */
+            SWPS_DEBUG("%s: internal error case\n", __func__);
+            err  = -2;
+            emsg = "internal error";
+            goto err_init_dev_topology;
+
+        default:
+            SWPS_DEBUG("%s: undefined error case\n", __func__);
+            emsg = "undefined error case";
+            goto err_init_dev_topology;
+    }
+    SWPS_DEBUG("%s: initial I2C topology success\n", __func__);
+    return 0;
+
+err_init_dev_topology:
+    SWPS_ERR("%s: %s <err>:%d\n", __func__, emsg, err);
+    return -1;
+}
+
+
+static int
+init_polling_task(void){
+
+    if (SWP_POLLING_ENABLE){
+        schedule_delayed_work(&swp_polling, _get_polling_period());
+    }
+    return 0;
+}
+
+
+static int
+init_swps_common(void){
+
+    char *err_msg = "ERR";
+    
+    auto_config = 0;
+    if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){
+        auto_config = 1;
+    }
+    if (register_modctl_device() < 0) {
+        err_msg = "register_modctl_device fail";
+        goto err_init_swps_common_1;
+    }
+    if (_update_auto_config_2_trnasvr() < 0) {
+        err_msg = "_update_auto_config_2_trnasvr fail";
+        goto err_init_swps_common_1;
+    }
+    if (init_polling_task() < 0){
+        err_msg = "init_polling_task fail";
+        goto err_init_swps_common_1;
+    }
+    return 0;
+
+err_init_swps_common_1:
+    clean_swps_common();
+    SWPS_ERR("%s: %s\n", __func__, err_msg);
+    return -1;
+}
+
+
+static int __init
+swp_module_init(void){
+
+    if (get_platform_type() < 0){
+        goto err_init_out;
+    }
+    if (get_layout_info() < 0){
+        goto err_init_out;
+    }
+    if (register_swp_module() < 0){
+        goto err_init_out;
+    }
+    if (create_ioexp_objs() < 0){
+        goto err_init_ioexp;
+    }
+    if (create_port_objs() < 0){
+        goto err_init_portobj;
+    }
+    if (init_mux_gpio(gpio_rest_mux) < 0){
+        goto err_init_mux;
+    }
+    if (init_dev_topology() < 0){
+        goto err_init_topology;
+    }
+    if (init_swps_common() < 0){
+        goto err_init_topology;
+    }
+    SWPS_INFO("Inventec switch-port module V.%s initial success.\n", SWP_VERSION);
+    return 0;
+
+
+err_init_topology:
+    clean_mux_gpio();
+err_init_mux:
+    clean_port_obj();
+err_init_portobj:
+    clean_ioexp_objs();
+err_init_ioexp:
+    class_unregister(swp_class_p);
+    class_destroy(swp_class_p);
+    unregister_chrdev_region(MKDEV(ctl_major, 0), 1);
+    unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+err_init_out:
+    SWPS_ERR("Inventec switch-port module V.%s initial failure.\n", SWP_VERSION);
+    return -1;
+}
+
+
+static void __exit
+swp_module_exit(void){
+
+    clean_swps_common();
+    clean_port_obj();
+    clean_ioexp_objs();
+    clean_mux_gpio();
+    class_unregister(swp_class_p);
+    class_destroy(swp_class_p);
+    unregister_chrdev_region(MKDEV(ctl_major, 0), 1);
+    unregister_chrdev_region(MKDEV(port_major, 0), port_total);
+    SWPS_INFO("Remove Inventec switch-port module success.\n");
+}
+
+
+/*  Module information  */
+MODULE_AUTHOR(SWP_AUTHOR);
+MODULE_DESCRIPTION(SWP_DESC);
+MODULE_VERSION(SWP_VERSION);
+MODULE_LICENSE(SWP_LICENSE);
+
+module_init(swp_module_init);
+module_exit(swp_module_exit);
+
+
+
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h
new file mode 100644
index 000000000000..d28a0a3c968e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h
@@ -0,0 +1,1164 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef INV_SWPS_H
+#define INV_SWPS_H
+
+#include "transceiver.h"
+#include "io_expander.h"
+#include "inv_mux.h"
+
+/* Module settings */
+#define SWP_CLS_NAME          "swps"
+#define SWP_DEV_PORT          "port"
+#define SWP_DEV_MODCTL        "module"
+#define SWP_RESET_PWD         "inventec"
+#define SWP_POLLING_PERIOD    (300)  /* msec */
+#define SWP_POLLING_ENABLE    (1)
+#define SWP_AUTOCONFIG_ENABLE (1)
+
+/* Module information */
+#define SWP_AUTHOR            "Neil <liao.neil@inventec.com>"
+#define SWP_DESC              "Inventec port and transceiver driver"
+#define SWP_VERSION           "4.2.9"
+#define SWP_LICENSE           "GPL"
+
+/* Module status define */
+#define SWP_STATE_NORMAL      (0)
+#define SWP_STATE_I2C_DIE     (-91)
+
+/* [Note]:
+ *  Functions and mechanism for auto-detect platform type is ready,
+ *  But HW and BIOS not ready! We need to wait them.
+ *  So, please do not use PLATFORM_TYPE_AUTO until they are ready.
+ *  (2016.06.13)
+ */
+#define PLATFORM_TYPE_AUTO                (100)
+#define PLATFORM_TYPE_MAGNOLIA            (111)
+#define PLATFORM_TYPE_MAGNOLIA_FNC        (112)
+#define PLATFORM_TYPE_REDWOOD             (121)
+#define PLATFORM_TYPE_REDWOOD_FSL         (122)
+#define PLATFORM_TYPE_HUDSON32I_GA        (131)
+#define PLATFORM_TYPE_SPRUCE              (141)
+#define PLATFORM_TYPE_CYPRESS_GA1         (151) /* Up -> Down */
+#define PLATFORM_TYPE_CYPRESS_GA2         (152) /* Down -> Up */
+#define PLATFORM_TYPE_CYPRESS_BAI         (153) /* Down -> Up */
+#define PLATFORM_TYPE_TAHOE               (161)
+#define PLATFORM_TYPE_SEQUOIA_GA          (171)
+#define PLATFORM_TYPE_LAVENDER_GA         (181)
+#define PLATFORM_TYPE_LAVENDER_ONL        (182)
+#define PLATFORM_TYPE_COTTONWOOD_RANGELEY (191)
+#define PLATFORM_TYPE_MAPLE               (201)
+/* Current running platfrom */
+#define PLATFORM_SETTINGS           PLATFORM_TYPE_MAPLE
+
+/* Define platform flag and kernel version */
+#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA)
+  #define SWPS_MAGNOLIA             (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC)
+  #define SWPS_MAGNOLIA             (1)
+  #define SWPS_KERN_VER_AF_3_10     (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD)
+  #define SWPS_REDWOOD              (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL)
+  #define SWPS_REDWOOD_FSL          (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA)
+  #define SWPS_HUDSON32I_GA         (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE)
+  #define SWPS_SPRUCE               (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1)
+  #define SWPS_CYPRESS_GA1          (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2)
+  #define SWPS_CYPRESS_GA2          (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI)
+  #define SWPS_CYPRESS_BAI          (1)
+  #define SWPS_KERN_VER_AF_3_10     (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE)
+  #define SWPS_TAHOE                (1)
+  #define SWPS_KERN_VER_AF_3_10     (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA)
+  #define SWPS_SEQUOIA              (1)
+  #define SWPS_KERN_VER_BF_3_8      (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA)
+  #define SWPS_LAVENDER             (1)
+  #define SWPS_KERN_VER_AF_3_10     (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL)
+  #define SWPS_LAVENDER             (1)
+  #define SWPS_KERN_VER_AF_3_10     (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_COTTONWOOD_RANGELEY)
+  #define SWPS_COTTONWOOD_RANGELEY  (1)
+  #define SWPS_KERN_VER_AF_3_10     (1)
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE)
+  #define SWPS_MAPLE                (1)
+  #define SWPS_KERN_VER_AF_3_10     (1)
+#endif
+
+
+struct inv_platform_s {
+    int  id;
+    char name[64];
+};
+
+struct inv_ioexp_layout_s {
+    int ioexp_id;
+    int ioexp_type;
+    struct ioexp_addr_s addr[4];
+};
+
+struct inv_port_layout_s {
+    int port_id;
+    int chan_id;
+    int ioexp_id;
+    int ioexp_offset;
+    int transvr_type;
+    int chipset_type;
+    int lane_id[8];
+};
+
+
+/* ==========================================
+ *   Inventec Platform Settings
+ * ==========================================
+ */
+struct inv_platform_s platform_map[] = {
+    {PLATFORM_TYPE_AUTO,                 "Auto-Detect"         },
+    {PLATFORM_TYPE_MAGNOLIA,             "Magnolia"            },
+    {PLATFORM_TYPE_MAGNOLIA_FNC,         "Magnolia_FNC"        },
+    {PLATFORM_TYPE_REDWOOD,              "Redwood"             },
+    {PLATFORM_TYPE_REDWOOD_FSL,          "Redwood_FSL"         },
+    {PLATFORM_TYPE_HUDSON32I_GA,         "Hudson32i"           },
+    {PLATFORM_TYPE_SPRUCE,               "Spruce"              },
+    {PLATFORM_TYPE_CYPRESS_GA1,          "Cypress_GA1"         },
+    {PLATFORM_TYPE_CYPRESS_GA2,          "Cypress_GA2"         },
+    {PLATFORM_TYPE_CYPRESS_BAI,          "Cypress_BAI"         },
+    {PLATFORM_TYPE_TAHOE,                "Tahoe"               },
+    {PLATFORM_TYPE_SEQUOIA_GA,           "Sequoia_GA"          },
+    {PLATFORM_TYPE_LAVENDER_GA,          "Lavender_GA"         },
+    {PLATFORM_TYPE_LAVENDER_ONL,         "Lavender_ONL"        },
+    {PLATFORM_TYPE_COTTONWOOD_RANGELEY,  "Cottonwood_RANGELEY" },
+    {PLATFORM_TYPE_MAPLE,                "Maple"               },
+};
+
+
+/* ==========================================
+ *   Magnolia Layout configuration
+ * ==========================================
+ */
+#ifdef SWPS_MAGNOLIA
+unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
+
+struct inv_ioexp_layout_s magnolia_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_MAGINOLIA_NAB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
+    },
+    {1,  IOEXP_TYPE_MAGINOLIA_NAB, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
+    },
+    {2,  IOEXP_TYPE_MAGINOLIA_NAB, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
+    },
+    {3,  IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander 4 A */
+                                     {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */
+    },
+    {4,  IOEXP_TYPE_MAGINOLIA_NAB, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
+    },
+    {5,  IOEXP_TYPE_MAGINOLIA_NAB, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
+    },
+    {6,  IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 7 A */
+                                     {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */
+    },
+};
+
+struct inv_port_layout_s magnolia_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  10,  0,  0, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 16} },
+    { 1,  11,  0,  1, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 15} },
+    { 2,  12,  0,  2, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 14} },
+    { 3,  13,  0,  3, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 13} },
+    { 4,  14,  0,  4, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 24} },
+    { 5,  15,  0,  5, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 23} },
+    { 6,  16,  0,  6, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 22} },
+    { 7,  17,  0,  7, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 21} },
+    { 8,  18,  1,  0, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 28} },
+    { 9,  19,  1,  1, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 27} },
+    {10,  20,  1,  2, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 26} },
+    {11,  21,  1,  3, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 25} },
+    {12,  22,  1,  4, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 32} },
+    {13,  23,  1,  5, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 31} },
+    {14,  24,  1,  6, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 30} },
+    {15,  25,  1,  7, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 29} },
+    {16,  26,  2,  0, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 48} },
+    {17,  27,  2,  1, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 47} },
+    {18,  28,  2,  2, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 46} },
+    {19,  29,  2,  3, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 45} },
+    {20,  30,  2,  4, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 52} },
+    {21,  31,  2,  5, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 51} },
+    {22,  32,  2,  6, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 50} },
+    {23,  33,  2,  7, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 49} },
+    {24,  34,  3,  0, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 56} },
+    {25,  35,  3,  1, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 55} },
+    {26,  36,  3,  2, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 54} },
+    {27,  37,  3,  3, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 53} },
+    {28,  38,  3,  4, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 60} },
+    {29,  39,  3,  5, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 59} },
+    {30,  40,  3,  6, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 58} },
+    {31,  41,  3,  7, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 57} },
+    {32,  42,  4,  0, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 64} },
+    {33,  43,  4,  1, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 63} },
+    {34,  44,  4,  2, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 62} },
+    {35,  45,  4,  3, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 61} },
+    {36,  46,  4,  4, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 68} },
+    {37,  47,  4,  5, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 67} },
+    {38,  48,  4,  6, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 66} },
+    {39,  49,  4,  7, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 65} },
+    {40,  50,  5,  0, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 72} },
+    {41,  51,  5,  1, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 71} },
+    {42,  52,  5,  2, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 70} },
+    {43,  53,  5,  3, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 69} },
+    {44,  54,  5,  4, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 76} },
+    {45,  55,  5,  5, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 75} },
+    {46,  56,  5,  6, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 74} },
+    {47,  57,  5,  7, TRANSVR_TYPE_SFP,  BCM_CHIP_TYPE_TRIDENT_2, { 73} },
+    {48,  58,  6,  0, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} },
+    {49,  59,  6,  1, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} },
+    {50,  60,  6,  2, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} },
+    {51,  61,  6,  3, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} },
+    {52,  62,  6,  4, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} },
+    {53,  63,  6,  5, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} },
+};
+#endif
+
+
+/* ==========================================
+ *   Redwood Layout configuration
+ * ==========================================
+ */
+#ifdef SWPS_REDWOOD
+unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
+
+struct inv_ioexp_layout_s redwood_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+    {1,  IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+    {2,  IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+    {3,  IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+};
+
+struct inv_port_layout_s redwood_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  22,  0,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  1,  2,  3,  4} },
+    { 1,  23,  0,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  5,  6,  7,  8} },
+    { 2,  24,  0,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  9, 10, 11, 12} },
+    { 3,  25,  0,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} },
+    { 4,  26,  0,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} },
+    { 5,  27,  0,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} },
+    { 6,  28,  0,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} },
+    { 7,  29,  0,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} },
+    { 8,  30,  1,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} },
+    { 9,  31,  1,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} },
+    {10,  32,  1,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} },
+    {11,  33,  1,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} },
+    {12,  34,  1,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} },
+    {13,  35,  1,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
+    {14,  36,  1,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} },
+    {15,  37,  1,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} },
+    {16,   6,  2,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
+    {17,   7,  2,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
+    {18,   8,  2,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} },
+    {19,   9,  2,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} },
+    {20,  10,  2,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
+    {21,  11,  2,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+    {22,  12,  2,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} },
+    {23,  13,  2,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} },
+    {24,  14,  3,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
+    {25,  15,  3,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
+    {26,  16,  3,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
+    {27,  17,  3,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
+    {28,  18,  3,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} },
+    {29,  19,  3,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
+    {30,  20,  3,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} },
+    {31,  21,  3,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} },
+};
+#endif
+
+
+/* ==========================================
+ *   Hudson32i Layout configuration
+ * ==========================================
+ */
+#ifdef SWPS_HUDSON32I_GA
+unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
+
+struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander A    */
+                                          {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander B    */
+                                          {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */
+    },
+    {1,  IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander A    */
+                                          {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander B    */
+                                          {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */
+    },
+    {2,  IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander A    */
+                                          {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander B    */
+                                          {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */
+    },
+    {3,  IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander A    */
+                                          {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander B    */
+                                          {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */
+    },
+};
+
+struct inv_port_layout_s hudson32iga_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,   6,  0,  0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {  1,  2,  3,  4} },
+    { 1,   7,  0,  1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {  5,  6,  7,  8} },
+    { 2,   8,  0,  2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {  9, 10, 11, 12} },
+    { 3,   9,  0,  3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 13, 14, 15, 16} },
+    { 4,  10,  0,  4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 17, 18, 19, 20} },
+    { 5,  11,  0,  5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 21, 22, 23, 24} },
+    { 6,  12,  0,  6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 25, 26, 27, 28} },
+    { 7,  13,  0,  7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 29, 30, 31, 32} },
+    { 8,  14,  1,  0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 33, 34, 35, 36} },
+    { 9,  15,  1,  1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 37, 38, 39, 40} },
+    {10,  16,  1,  2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 41, 42, 43, 44} },
+    {11,  17,  1,  3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 45, 46, 47, 48} },
+    {12,  18,  1,  4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 49, 50, 51, 52} },
+    {13,  19,  1,  5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 53, 54, 55, 56} },
+    {14,  20,  1,  6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 57, 58, 59, 60} },
+    {15,  21,  1,  7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 61, 62, 63, 64} },
+    {16,  22,  2,  0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 65, 66, 67, 68} },
+    {17,  23,  2,  1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 69, 70, 71, 72} },
+    {18,  24,  2,  2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 73, 74, 75, 76} },
+    {19,  25,  2,  3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} },
+    {20,  26,  2,  4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} },
+    {21,  27,  2,  5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 85, 86, 87, 88} },
+    {22,  28,  2,  6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 89, 90, 91, 92} },
+    {23,  29,  2,  7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 93, 94, 95, 96} },
+    {24,  30,  3,  0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} },
+    {25,  31,  3,  1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} },
+    {26,  32,  3,  2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} },
+    {27,  33,  3,  3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} },
+    {28,  34,  3,  4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {113,114,115,116} },
+    {29,  35,  3,  5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {117,118,119,120} },
+    {30,  36,  3,  6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {121,122,123,124} },
+    {31,  37,  3,  7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {125,126,127,128} },
+};
+#endif
+
+
+/* ==========================================
+ *   Spruce Layout configuration
+ * ==========================================
+ */
+#ifdef SWPS_SPRUCE
+unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
+
+struct inv_ioexp_layout_s spruce_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_SPRUCE_7AB,  { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 7A  */
+                                   {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B  */
+    },
+};
+
+struct inv_port_layout_s spruce_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,   6,  0,  0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} },
+    { 1,   7,  0,  1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} },
+    { 2,   8,  0,  2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} },
+    { 3,   9,  0,  3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} },
+    { 4,  10,  0,  4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} },
+    { 5,  11,  0,  5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} },
+};
+#endif
+
+
+/* ==========================================
+ *   Cypress Layout configuration (Inventec version [Up->Down])
+ * ==========================================
+ */
+#ifdef SWPS_CYPRESS_GA1
+unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548;
+
+struct inv_ioexp_layout_s cypress_ga1_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_CYPRESS_NABC,  { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {1,  IOEXP_TYPE_CYPRESS_NABC,  { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {2,  IOEXP_TYPE_CYPRESS_NABC,  { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {3,  IOEXP_TYPE_CYPRESS_NABC,  { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {4,  IOEXP_TYPE_CYPRESS_NABC,  { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {5,  IOEXP_TYPE_CYPRESS_NABC,  { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {6,  IOEXP_TYPE_CYPRESS_7ABC,  { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, },    /* addr[0] = I/O Expander 7 A */
+                                     {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, },    /* addr[1] = I/O Expander 7 B */
+                                     {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
+    },
+};
+
+struct inv_port_layout_s cypress_ga1_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  10,  0,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  1} },
+    { 1,  11,  0,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  2} },
+    { 2,  12,  0,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  3} },
+    { 3,  13,  0,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  4} },
+    { 4,  14,  0,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  5} },
+    { 5,  15,  0,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  6} },
+    { 6,  16,  0,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  7} },
+    { 7,  17,  0,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  8} },
+    { 8,  18,  1,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  9} },
+    { 9,  19,  1,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 10} },
+    {10,  20,  1,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 11} },
+    {11,  21,  1,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 12} },
+    {12,  22,  1,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 21} },
+    {13,  23,  1,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 22} },
+    {14,  24,  1,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 23} },
+    {15,  25,  1,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 24} },
+    {16,  26,  2,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 33} },
+    {17,  27,  2,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 34} },
+    {18,  28,  2,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 35} },
+    {19,  29,  2,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 36} },
+    {20,  30,  2,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 37} },
+    {21,  31,  2,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 38} },
+    {22,  32,  2,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 39} },
+    {23,  33,  2,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 40} },
+    {24,  34,  3,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 41} },
+    {25,  35,  3,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 42} },
+    {26,  36,  3,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 43} },
+    {27,  37,  3,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 44} },
+    {28,  38,  3,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 49} },
+    {29,  39,  3,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 50} },
+    {30,  40,  3,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 51} },
+    {31,  41,  3,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 52} },
+    {32,  42,  4,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 53} },
+    {33,  43,  4,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 54} },
+    {34,  44,  4,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 55} },
+    {35,  45,  4,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 56} },
+    {36,  46,  4,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 65} },
+    {37,  47,  4,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 66} },
+    {38,  48,  4,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 67} },
+    {39,  49,  4,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 68} },
+    {40,  50,  5,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 69} },
+    {41,  51,  5,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 70} },
+    {42,  52,  5,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 71} },
+    {43,  53,  5,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 72} },
+    {44,  54,  5,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 81} },
+    {45,  55,  5,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 82} },
+    {46,  56,  5,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 83} },
+    {47,  57,  5,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 84} },
+    {48,  58,  6,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
+    {49,  59,  6,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+    {50,  60,  6,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
+    {51,  61,  6,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
+    {52,  62,  6,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
+    {53,  63,  6,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
+};
+#endif
+
+
+/* ==========================================
+ *   Cypress Layout configuration (Inventec version [Down->Up])
+ * ==========================================
+ */
+#ifdef SWPS_CYPRESS_GA2
+unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA;
+
+struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_CYPRESS_NABC,  { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {1,  IOEXP_TYPE_CYPRESS_NABC,  { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {2,  IOEXP_TYPE_CYPRESS_NABC,  { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {3,  IOEXP_TYPE_CYPRESS_NABC,  { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {4,  IOEXP_TYPE_CYPRESS_NABC,  { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {5,  IOEXP_TYPE_CYPRESS_NABC,  { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {6,  IOEXP_TYPE_CYPRESS_7ABC,  { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, },    /* addr[0] = I/O Expander 7 A */
+                                     {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, },    /* addr[1] = I/O Expander 7 B */
+                                     {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
+    },
+};
+
+struct inv_port_layout_s cypress_ga2_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  11,  0,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  2} },
+    { 1,  10,  0,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  1} },
+    { 2,  13,  0,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  4} },
+    { 3,  12,  0,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  3} },
+    { 4,  15,  0,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  6} },
+    { 5,  14,  0,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  5} },
+    { 6,  17,  0,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  8} },
+    { 7,  16,  0,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  7} },
+    { 8,  19,  1,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 10} },
+    { 9,  18,  1,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  9} },
+    {10,  21,  1,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 12} },
+    {11,  20,  1,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 11} },
+    {12,  23,  1,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 22} },
+    {13,  22,  1,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 21} },
+    {14,  25,  1,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 24} },
+    {15,  24,  1,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 23} },
+    {16,  27,  2,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 34} },
+    {17,  26,  2,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 33} },
+    {18,  29,  2,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 36} },
+    {19,  28,  2,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 35} },
+    {20,  31,  2,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 38} },
+    {21,  30,  2,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 37} },
+    {22,  33,  2,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 40} },
+    {23,  32,  2,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 39} },
+    {24,  35,  3,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 42} },
+    {25,  34,  3,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 41} },
+    {26,  37,  3,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 44} },
+    {27,  36,  3,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 43} },
+    {28,  39,  3,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 50} },
+    {29,  38,  3,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 49} },
+    {30,  41,  3,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 52} },
+    {31,  40,  3,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 51} },
+    {32,  43,  4,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 54} },
+    {33,  42,  4,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 53} },
+    {34,  45,  4,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 56} },
+    {35,  44,  4,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 55} },
+    {36,  47,  4,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 66} },
+    {37,  46,  4,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 65} },
+    {38,  49,  4,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 68} },
+    {39,  48,  4,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 67} },
+    {40,  51,  5,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 70} },
+    {41,  50,  5,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 69} },
+    {42,  53,  5,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 72} },
+    {43,  52,  5,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 71} },
+    {44,  55,  5,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 82} },
+    {45,  54,  5,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 81} },
+    {46,  57,  5,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 84} },
+    {47,  56,  5,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 83} },
+    {48,  59,  6,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+    {49,  58,  6,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
+    {50,  61,  6,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
+    {51,  60,  6,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
+    {52,  63,  6,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
+    {53,  62,  6,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
+};
+#endif
+
+
+/* ==========================================
+ *   Cypress Layout configuration (BaiDu version)
+ * ==========================================
+ */
+#ifdef SWPS_CYPRESS_BAI
+unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA;
+
+struct inv_ioexp_layout_s cypress_b_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_CYPRESS_NABC,  { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {1,  IOEXP_TYPE_CYPRESS_NABC,  { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {2,  IOEXP_TYPE_CYPRESS_NABC,  { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {3,  IOEXP_TYPE_CYPRESS_NABC,  { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {4,  IOEXP_TYPE_CYPRESS_NABC,  { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {5,  IOEXP_TYPE_CYPRESS_NABC,  { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                     {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                     {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {6,  IOEXP_TYPE_CYPRESS_7ABC,  { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, },    /* addr[0] = I/O Expander 7 A */
+                                     {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, },    /* addr[1] = I/O Expander 7 B */
+                                     {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
+    },
+};
+
+struct inv_port_layout_s cypress_b_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 1,  11,  0,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  2} },
+    { 2,  10,  0,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  1} },
+    { 3,  13,  0,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  4} },
+    { 4,  12,  0,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  3} },
+    { 5,  15,  0,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  6} },
+    { 6,  14,  0,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  5} },
+    { 7,  17,  0,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  8} },
+    { 8,  16,  0,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  7} },
+    { 9,  19,  1,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 10} },
+    {10,  18,  1,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, {  9} },
+    {11,  21,  1,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 12} },
+    {12,  20,  1,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 11} },
+    {13,  23,  1,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 22} },
+    {14,  22,  1,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 21} },
+    {15,  25,  1,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 24} },
+    {16,  24,  1,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 23} },
+    {17,  27,  2,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 34} },
+    {18,  26,  2,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 33} },
+    {19,  29,  2,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 36} },
+    {20,  28,  2,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 35} },
+    {21,  31,  2,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 38} },
+    {22,  30,  2,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 37} },
+    {23,  33,  2,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 40} },
+    {24,  32,  2,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 39} },
+    {25,  35,  3,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 42} },
+    {26,  34,  3,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 41} },
+    {27,  37,  3,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 44} },
+    {28,  36,  3,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 43} },
+    {29,  39,  3,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 50} },
+    {30,  38,  3,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 49} },
+    {31,  41,  3,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 52} },
+    {32,  40,  3,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 51} },
+    {33,  43,  4,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 54} },
+    {34,  42,  4,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 53} },
+    {35,  45,  4,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 56} },
+    {36,  44,  4,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 55} },
+    {37,  47,  4,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 66} },
+    {38,  46,  4,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 65} },
+    {39,  49,  4,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 68} },
+    {40,  48,  4,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 67} },
+    {41,  51,  5,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 70} },
+    {42,  50,  5,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 69} },
+    {43,  53,  5,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 72} },
+    {44,  52,  5,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 71} },
+    {45,  55,  5,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 82} },
+    {46,  54,  5,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 81} },
+    {47,  57,  5,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 84} },
+    {48,  56,  5,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TOMAHAWK, { 83} },
+    {49,  59,  6,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+    {50,  58,  6,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
+    {51,  61,  6,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
+    {52,  60,  6,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
+    {53,  63,  6,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
+    {54,  62,  6,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
+};
+#endif
+
+
+/* ==========================================
+ *   Redwood_fsl Layout configuration
+ * ==========================================
+ */
+#ifdef SWPS_REDWOOD_FSL
+unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
+
+struct inv_ioexp_layout_s redwood_fsl_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+    {1,  IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+    {2,  IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+    {3,  IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[0] = I/O Expander 1-4 A */
+                                      {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, },    /* addr[1] = I/O Expander 1-4 B */
+                                      {0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B   */
+    },
+};
+
+
+struct inv_port_layout_s redwood_fsl_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  22,  0,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  1,  2,  3,  4} },
+    { 1,  23,  0,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  5,  6,  7,  8} },
+    { 2,  24,  0,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  9, 10, 11, 12} },
+    { 3,  25,  0,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} },
+    { 4,  26,  0,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} },
+    { 5,  27,  0,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} },
+    { 6,  28,  0,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} },
+    { 7,  29,  0,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} },
+    { 8,  30,  1,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} },
+    { 9,  31,  1,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} },
+    {10,  32,  1,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} },
+    {11,  33,  1,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} },
+    {12,  34,  1,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} },
+    {13,  35,  1,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
+    {14,  36,  1,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} },
+    {15,  37,  1,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} },
+    {16,   6,  2,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
+    {17,   7,  2,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
+    {18,   8,  2,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} },
+    {19,   9,  2,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} },
+    {20,  10,  2,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
+    {21,  11,  2,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
+    {22,  12,  2,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} },
+    {23,  13,  2,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} },
+    {24,  14,  3,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
+    {25,  15,  3,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
+    {26,  16,  3,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
+    {27,  17,  3,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
+    {28,  18,  3,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} },
+    {29,  19,  3,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
+    {30,  20,  3,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} },
+    {31,  21,  3,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} },
+};
+#endif
+
+
+/* ==========================================
+ *   Tahoe Layout configuration
+ * ==========================================
+ */
+#ifdef SWPS_TAHOE
+unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548;
+
+struct inv_ioexp_layout_s tahoe_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, },    /* addr[0] = I/O Expander 6 A */
+                                  {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, },    /* addr[1] = I/O Expander 6 B */
+                                  {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */
+    },
+    {1,  IOEXP_TYPE_TAHOE_5A,   { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */
+    },
+};
+
+
+struct inv_port_layout_s tahoe_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  12,  1,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65,  66,  67,  68} },
+    { 1,  11,  1,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53,  54,  55,  56} },
+    { 2,  22,  0,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69,  70,  71,  72} },
+    { 3,  21,  0,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81,  82,  83,  84} },
+    { 4,  24,  0,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97,  98,  99, 100} },
+    { 5,  23,  0,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85,  86,  87,  88} },
+    { 6,  18,  0,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} },
+    { 7,  17,  0,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} },
+    { 8,  20,  0,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} },
+    { 9,  19,  0,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} },
+};
+#endif
+
+
+/* ==========================================
+ *   Sequoia Layout configuration
+ * ==========================================
+ */
+#ifdef SWPS_SEQUOIA
+unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548;
+
+struct inv_ioexp_layout_s sequoia_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_SEQUOIA_NABC, { {1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 0 A */
+                                    {1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 0 B */
+                                    {1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */
+    },
+    {1,  IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 1 A */
+                                    {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 1 B */
+                                    {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */
+    },
+    {2,  IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 2 A */
+                                    {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 2 B */
+                                    {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */
+    },
+    {3,  IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 3 A */
+                                    {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 3 B */
+                                    {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */
+    },
+    {4,  IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 4 A */
+                                    {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 4 B */
+                                    {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */
+    },
+    {5,  IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 5 A */
+                                    {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 5 B */
+                                    {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */
+    },
+    {6,  IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 6 A */
+                                    {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 6 B */
+                                    {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */
+    },
+    {7,  IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 7 A */
+                                    {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 7 B */
+                                    {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
+    },
+};
+
+
+struct inv_port_layout_s sequoia_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,   9,  0,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  9,  10,  11,  12} },
+    { 1,  10,  0,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  1,   2,   3,   4} },
+    { 2,  11,  0,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25,  26,  27,  28} },
+    { 3,  12,  0,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17,  18,  19,  20} },
+    { 4,  13,  0,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41,  42,  43,  44} },
+    { 5,  14,  0,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33,  34,  35,  36} },
+    { 6,  15,  0,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57,  58,  59,  60} },
+    { 7,  16,  0,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49,  50,  51,  52} },
+    { 8,  17,  1,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73,  74,  75,  76} },
+    { 9,  18,  1,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65,  66,  67,  68} },
+    {10,  19,  1,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89,  90,  91,  92} },
+    {11,  20,  1,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81,  82,  83,  84} },
+    {12,  21,  1,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} },
+    {13,  22,  1,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97,  98,  99, 100} },
+    {14,  23,  1,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} },
+    {15,  24,  1,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} },
+    {16,  25,  2,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} },
+    {17,  26,  2,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} },
+    {18,  27,  2,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} },
+    {19,  28,  2,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} },
+    {20,  29,  2,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} },
+    {21,  30,  2,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} },
+    {22,  31,  2,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} },
+    {23,  32,  2,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} },
+    {24,  33,  3,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} },
+    {25,  34,  3,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} },
+    {26,  35,  3,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} },
+    {27,  36,  3,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} },
+    {28,  37,  3,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} },
+    {29,  38,  3,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} },
+    {30,  39,  3,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} },
+    {31,  40,  3,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} },
+    {32,  44,  4,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13,  14,  15,  16} },
+    {33,  43,  4,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {  5,   6,   7,   8} },
+    {34,  42,  4,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29,  30,  31,  32} },
+    {35,  41,  4,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21,  22,  23,  24} },
+    {36,  48,  4,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45,  46,  47,  48} },
+    {37,  47,  4,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37,  38,  39,  40} },
+    {38,  46,  4,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61,  62,  63,  64} },
+    {39,  45,  4,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53,  54,  55,  56} },
+    {40,  52,  5,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77,  78,  79,  80} },
+    {41,  51,  5,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69,  70,  71,  72} },
+    {42,  50,  5,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93,  94,  95,  96} },
+    {43,  49,  5,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85,  86,  87,  88} },
+    {44,  56,  5,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} },
+    {45,  55,  5,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} },
+    {46,  54,  5,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} },
+    {47,  53,  5,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} },
+    {48,  60,  6,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} },
+    {49,  59,  6,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} },
+    {50,  58,  6,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} },
+    {51,  57,  6,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} },
+    {52,  64,  6,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} },
+    {53,  63,  6,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} },
+    {54,  62,  6,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} },
+    {55,  61,  6,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} },
+    {56,  68,  7,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} },
+    {57,  67,  7,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} },
+    {58,  66,  7,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} },
+    {59,  65,  7,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} },
+    {60,  72,  7,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} },
+    {61,  71,  7,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} },
+    {62,  70,  7,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} },
+    {63,  69,  7,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} },
+};
+#endif
+
+
+/* ==========================================
+ *   Lavender Layout configuration
+ * ==========================================
+ */
+#if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA)
+unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548;
+#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL)
+unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548;
+#endif
+
+#ifdef SWPS_LAVENDER
+struct inv_ioexp_layout_s lavender_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_SEQUOIA_NABC, { { 1, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 0 A */
+                                    { 1, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 0 B */
+                                    { 1, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */
+    },
+    {1,  IOEXP_TYPE_SEQUOIA_NABC, { { 2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 1 A */
+                                    { 2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 1 B */
+                                    { 2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */
+    },
+    {2,  IOEXP_TYPE_SEQUOIA_NABC, { { 3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 2 A */
+                                    { 3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 2 B */
+                                    { 3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */
+    },
+    {3,  IOEXP_TYPE_SEQUOIA_NABC, { { 4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 3 A */
+                                    { 4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 3 B */
+                                    { 4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */
+    },
+    {4,  IOEXP_TYPE_SEQUOIA_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 4 A */
+                                    { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 4 B */
+                                    { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */
+    },
+    {5,  IOEXP_TYPE_SEQUOIA_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 5 A */
+                                    {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 5 B */
+                                    {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */
+    },
+    {6,  IOEXP_TYPE_SEQUOIA_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 6 A */
+                                    {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 6 B */
+                                    {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */
+    },
+    {7,  IOEXP_TYPE_SEQUOIA_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 7 A */
+                                    {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 7 B */
+                                    {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
+    },
+    {8,  IOEXP_TYPE_LAVENDER_P65, { { 5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xF6, 0xff}, {0xF8, 0xff}, }, }, /* addr[0] = I/O Expander CPU */
+    },
+};
+
+
+struct inv_port_layout_s lavender_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  17,  0,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {188, 189, 190, 191} },
+    { 1,  18,  0,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {184, 185, 186, 187} },
+    { 2,  19,  0,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {180, 181, 182, 183} },
+    { 3,  20,  0,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {176, 177, 178, 179} },
+    { 4,  21,  0,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {172, 173, 174, 175} },
+    { 5,  22,  0,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {168, 169, 170, 171} },
+    { 6,  23,  0,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {164, 165, 166, 167} },
+    { 7,  24,  0,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {160, 161, 162, 163} },
+    { 8,  25,  1,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {156, 157, 158, 159} },
+    { 9,  26,  1,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {152, 153, 154, 155} },
+    {10,  27,  1,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {148, 149, 150, 151} },
+    {11,  28,  1,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {144, 145, 146, 147} },
+    {12,  29,  1,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {140, 141, 142, 143} },
+    {13,  30,  1,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {136, 137, 138, 139} },
+    {14,  31,  1,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {132, 133, 134, 135} },
+    {15,  32,  1,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {128, 129, 130, 131} },
+    {16,  33,  2,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {  0,   1,   2,   3} },
+    {17,  34,  2,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {  4,   5,   6,   7} },
+    {18,  35,  2,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {  8,   9,  10,  11} },
+    {19,  36,  2,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 12,  13,  14,  15} },
+    {20,  37,  2,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 16,  17,  18,  19} },
+    {21,  38,  2,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 20,  21,  22,  23} },
+    {22,  39,  2,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 24,  25,  26,  27} },
+    {23,  40,  2,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 28,  29,  30,  31} },
+    {24,  41,  3,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 32,  33,  34,  35} },
+    {25,  42,  3,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 36,  37,  38,  39} },
+    {26,  43,  3,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 40,  41,  42,  43} },
+    {27,  44,  3,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 44,  45,  46,  47} },
+    {28,  45,  3,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 48,  49,  50,  51} },
+    {29,  46,  3,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 52,  53,  54,  55} },
+    {30,  47,  3,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 56,  57,  58,  59} },
+    {31,  48,  3,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 60,  61,  62,  63} },
+    {32,  49,  4,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {256, 257, 258, 259} },
+    {33,  50,  4,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {260, 261, 262, 263} },
+    {34,  51,  4,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {264, 265, 266, 267} },
+    {35,  52,  4,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {268, 269, 270, 271} },
+    {36,  53,  4,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {272, 273, 274, 275} },
+    {37,  54,  4,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {276, 277, 278, 279} },
+    {38,  55,  4,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {280, 281, 282, 283} },
+    {39,  56,  4,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {284, 285, 286, 287} },
+    {40,  57,  5,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {288, 289, 290, 291} },
+    {41,  58,  5,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {292, 293, 294, 295} },
+    {42,  59,  5,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {296, 297, 298, 299} },
+    {43,  60,  5,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {300, 301, 302, 303} },
+    {44,  61,  5,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {304, 305, 306, 307} },
+    {45,  62,  5,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {308, 309, 310, 311} },
+    {46,  63,  5,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {312, 313, 314, 315} },
+    {47,  64,  5,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {316, 317, 318, 319} },
+    {48,  65,  6,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {444, 445, 446, 447} },
+    {49,  66,  6,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {440, 441, 442, 443} },
+    {50,  67,  6,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {436, 437, 438, 439} },
+    {51,  68,  6,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {432, 433, 434, 435} },
+    {52,  69,  6,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {428, 429, 430, 431} },
+    {53,  70,  6,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {424, 425, 426, 427} },
+    {54,  71,  6,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {420, 421, 422, 423} },
+    {55,  72,  6,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {416, 417, 418, 419} },
+    {56,  73,  7,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {412, 413, 414, 415} },
+    {57,  74,  7,  1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {408, 409, 410, 411} },
+    {58,  75,  7,  2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {404, 405, 406, 407} },
+    {59,  76,  7,  3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {400, 401, 402, 403} },
+    {60,  77,  7,  4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {396, 397, 398, 399} },
+    {61,  78,  7,  5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {392, 393, 394, 395} },
+    {62,  79,  7,  6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {388, 389, 390, 391} },
+    {63,  80,  7,  7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {384, 385, 386, 387} },
+    {64,   5,  8,  0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 64,  65,  66,  67} },
+};
+#endif
+
+/* ===========================================================
+ *   Cottonwood Layout configuration Rangeley (Rangeley CPU board)
+ * ===========================================================
+ */
+#ifdef SWPS_COTTONWOOD_RANGELEY
+unsigned cottonwood_rangeley_gpio_rest_mux = MUX_RST_GPIO_500_PAC9548;
+
+struct inv_ioexp_layout_s cottonwood_rangeley_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  CPLD_TYPE_COTTONWOOD,{ {1, 0x55, {22, 23, 24, 25}, {22, 23, 24, 25}, {-1, -1, -1, -1}, {0xee, 0xee, 0x99, 0x99}, {0x00, 0x00, 0x00, 0x00}, },
+                              },
+    },
+};
+
+
+struct inv_port_layout_s cottonwood_rangeley_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHI_TYPE / LANE_ID */
+    { 0,  2,  0,  0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 75} },
+    { 1,  3,  0,  1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 77} },
+    { 2,  4,  0,  2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 79} },
+    { 3,  5,  0,  3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} },
+};
+#endif
+
+/* ===========================================================
+ *   Maple Layout configuration
+ * ===========================================================
+ */
+#ifdef SWPS_MAPLE
+unsigned maple_gpio_rest_mux = 249;
+
+struct inv_ioexp_layout_s maple_ioexp_layout[] = {
+    /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
+    {0,  IOEXP_TYPE_MAPLE_0ABC,   { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, },    /* addr[0] = I/O Expander 0 A */
+                                    {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, },    /* addr[1] = I/O Expander 0 B */
+                                    {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */
+    },
+    {1,  IOEXP_TYPE_MAPLE_NABC,   { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                    {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                    {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {2,  IOEXP_TYPE_MAPLE_NABC,   { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                    {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                    {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {3,  IOEXP_TYPE_MAPLE_NABC,   { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                    {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                    {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {4,  IOEXP_TYPE_MAPLE_NABC,   { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                    {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                    {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {5,  IOEXP_TYPE_MAPLE_NABC,   { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                    {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                    {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+    {6,  IOEXP_TYPE_MAPLE_NABC,   { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[0] = I/O Expander N A */
+                                    {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, },    /* addr[1] = I/O Expander N B */
+                                    {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
+    },
+};
+
+struct inv_port_layout_s maple_port_layout[] = {
+    /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
+    { 0,  18,  1,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  1} },
+    { 1,  19,  1,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  2} },
+    { 2,  20,  1,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  3} },
+    { 3,  21,  1,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  4} },
+    { 4,  22,  1,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  5} },
+    { 5,  23,  1,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  6} },
+    { 6,  24,  1,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  7} },
+    { 7,  25,  1,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, {  8} },
+    { 8,  26,  2,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 13} },
+    { 9,  27,  2,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 14} },
+    {10,  28,  2,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 15} },
+    {11,  29,  2,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 16} },
+    {12,  30,  2,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 21} },
+    {13,  31,  2,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 22} },
+    {14,  32,  2,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 23} },
+    {15,  33,  2,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 24} },
+    {16,  34,  3,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 29} },
+    {17,  35,  3,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 30} },
+    {18,  36,  3,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 31} },
+    {19,  37,  3,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 32} },
+    {20,  38,  3,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 33} },
+    {21,  39,  3,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 34} },
+    {22,  40,  3,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 35} },
+    {23,  41,  3,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 36} },
+    {24,  42,  4,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 41} },
+    {25,  43,  4,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 42} },
+    {26,  44,  4,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 43} },
+    {27,  45,  4,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 44} },
+    {28,  46,  4,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 49} },
+    {29,  47,  4,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 50} },
+    {30,  48,  4,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 51} },
+    {31,  49,  4,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 52} },
+    {32,  50,  5,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 57} },
+    {33,  51,  5,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 58} },
+    {34,  52,  5,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 59} },
+    {35,  53,  5,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 60} },
+    {36,  54,  5,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 61} },
+    {37,  55,  5,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 62} },
+    {38,  56,  5,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 63} },
+    {39,  57,  5,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 64} },
+    {40,  58,  6,  0, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 65} },
+    {41,  59,  6,  1, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 66} },
+    {42,  60,  6,  2, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 67} },
+    {43,  61,  6,  3, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 68} },
+    {44,  62,  6,  4, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 69} },
+    {45,  63,  6,  5, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 70} },
+    {46,  64,  6,  6, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 71} },
+    {47,  65,  6,  7, TRANSVR_TYPE_SFP,     BCM_CHIP_TYPE_TRIDENT_3, { 72} },
+    {48,  10,  0,  0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} },
+    {49,  11,  0,  1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} },
+    {50,  12,  0,  2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} },
+    {51,  13,  0,  3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 97, 98, 99,100} },
+    {52,  14,  0,  4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {105,106,107,108} },
+    {53,  15,  0,  5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {113,114,115,116} },
+    {54,  16,  0,  6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {121,122,123,124} },
+    {55,  17,  0,  7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {125,126,127,128} },
+};
+#endif
+
+#endif /* INV_SWPS_H */
+
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c
new file mode 100644
index 000000000000..4564b5855fd8
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c
@@ -0,0 +1,2046 @@
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include "io_expander.h"
+
+static struct ioexp_obj_s *ioexp_head_p = NULL;
+static struct ioexp_obj_s *ioexp_tail_p = NULL;
+
+
+/* ========== Register IOEXP layout ==========
+ */
+struct ioexp_map_s ioexp_map_magnolia_nab = {
+
+    .chip_amount = 2,
+    .data_width  = 2,
+
+    .map_present    = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X)   */
+                        {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+                        {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+                        {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+                        {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */
+                        {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */
+                        {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */
+                        {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */
+    },
+    .map_tx_fault   = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X)   */
+                        {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+                        {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+                        {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+                        {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */
+                        {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */
+                        {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */
+                        {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */
+    },
+    .map_rxlos      = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X)   */
+                        {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+                        {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+                        {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+                        {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */
+                        {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */
+                        {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */
+                        {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_magnolia_4ab = {
+
+    .chip_amount = 2,
+    .data_width  = 2,
+
+    .map_present    = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X)   */
+                        {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+                        {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+                        {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+                        {1, 0, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */
+                        {1, 0, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */
+                        {1, 0, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */
+                        {1, 0, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */
+    },
+    .map_tx_fault   = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X)   */
+                        {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+                        {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+                        {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+                        {1, 1, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */
+                        {1, 1, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */
+                        {1, 1, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */
+                        {1, 1, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */
+    },
+    .map_rxlos      = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X)   */
+                        {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+                        {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+                        {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+                        {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */
+                        {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */
+                        {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */
+                        {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_magnolia_7ab = {
+
+    .chip_amount    = 2,
+    .data_width     = 2,
+
+    .map_present    = { {1, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {1, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {1, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {1, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {1, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+    },
+    .map_reset      = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X)   */
+                        {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+                        {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+                        {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */
+                        {1, 0, 0}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */
+                        {1, 0, 1}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */
+    },
+    .map_lpmod      = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP_P(X)   */
+                        {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+                        {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+                        {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */
+                        {1, 0, 2}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */
+                        {1, 0, 3}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */
+    },
+    .map_modsel     = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP_N_P(X)   */
+                        {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+                        {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+                        {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */
+                        {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */
+                        {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_redwood_p01p08_p17p24 = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {2, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {2, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_reset      = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X)   */
+                        {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+                        {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+                        {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+                        {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+                        {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+                        {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+                        {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+    },
+    .map_lpmod      = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X)   */
+                        {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+                        {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+                        {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+                        {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+                        {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+                        {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+                        {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+    },
+    .map_modsel     = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X)   */
+                        {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+                        {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+                        {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+                        {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+                        {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+                        {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+                        {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_redwood_p09p16_p25p32 = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_reset      = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X)   */
+                        {0, 0, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+                        {0, 0, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+                        {0, 0, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+                        {1, 0, 0}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+                        {1, 0, 1}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+                        {1, 0, 2}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+                        {1, 0, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+    },
+    .map_lpmod      = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP28_P(X)   */
+                        {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+                        {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+                        {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+                        {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+                        {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+                        {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+                        {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+    },
+    .map_modsel     = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X)   */
+                        {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+                        {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+                        {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+                        {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+                        {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+                        {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+                        {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_hudson32iga_p01p08_p17p24 = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {2, 0, 0}, /* map_present[0] = MODABS_QSFP(X)   */
+                        {2, 0, 1}, /* map_present[1] = MODABS_QSFP(X+1) */
+                        {2, 0, 2}, /* map_present[2] = MODABS_QSFP(X+2) */
+                        {2, 0, 3}, /* map_present[3] = MODABS_QSFP(X+3) */
+                        {2, 0, 4}, /* map_present[4] = MODABS_QSFP(X+4) */
+                        {2, 0, 5}, /* map_present[5] = MODABS_QSFP(X+5) */
+                        {2, 0, 6}, /* map_present[6] = MODABS_QSFP(X+6) */
+                        {2, 0, 7}, /* map_present[7] = MODABS_QSFP(X+7) */
+    },
+    .map_reset      = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X)   */
+                        {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */
+                        {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */
+                        {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */
+                        {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */
+                        {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */
+                        {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */
+                        {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */
+    },
+    .map_lpmod      = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X)   */
+                        {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */
+                        {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */
+                        {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */
+                        {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */
+                        {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */
+                        {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */
+                        {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */
+    },
+    .map_modsel     = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X)   */
+                        {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */
+                        {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */
+                        {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */
+                        {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */
+                        {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */
+                        {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */
+                        {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_hudson32iga_p09p16_p25p32 = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {2, 1, 0}, /* map_present[0] = MODABS_QSFP(X)   */
+                        {2, 1, 1}, /* map_present[1] = MODABS_QSFP(X+1) */
+                        {2, 1, 2}, /* map_present[2] = MODABS_QSFP(X+2) */
+                        {2, 1, 3}, /* map_present[3] = MODABS_QSFP(X+3) */
+                        {2, 1, 4}, /* map_present[4] = MODABS_QSFP(X+4) */
+                        {2, 1, 5}, /* map_present[5] = MODABS_QSFP(X+5) */
+                        {2, 1, 6}, /* map_present[6] = MODABS_QSFP(X+6) */
+                        {2, 1, 7}, /* map_present[7] = MODABS_QSFP(X+7) */
+    },
+    .map_reset      = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP(X)   */
+                        {0, 0, 1}, /* map_reset[1] = QRESET_QSFP(X+1) */
+                        {0, 0, 2}, /* map_reset[2] = QRESET_QSFP(X+2) */
+                        {0, 0, 3}, /* map_reset[3] = QRESET_QSFP(X+3) */
+                        {1, 0, 0}, /* map_reset[4] = QRESET_QSFP(X+4) */
+                        {1, 0, 1}, /* map_reset[5] = QRESET_QSFP(X+5) */
+                        {1, 0, 2}, /* map_reset[6] = QRESET_QSFP(X+6) */
+                        {1, 0, 3}, /* map_reset[7] = QRESET_QSFP(X+7) */
+    },
+    .map_lpmod      = { {0, 0, 4}, /* map_lpmod[0] = LPMODE_QSFP(X)   */
+                        {0, 0, 5}, /* map_lpmod[1] = LPMODE_QSFP(X+1) */
+                        {0, 0, 6}, /* map_lpmod[2] = LPMODE_QSFP(X+2) */
+                        {0, 0, 7}, /* map_lpmod[3] = LPMODE_QSFP(X+3) */
+                        {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP(X+4) */
+                        {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP(X+5) */
+                        {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP(X+6) */
+                        {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP(X+7) */
+    },
+    .map_modsel     = { {0, 1, 4}, /* map_modsel[0] = MODSEL_QSFP(X)   */
+                        {0, 1, 5}, /* map_modsel[1] = MODSEL_QSFP(X+1) */
+                        {0, 1, 6}, /* map_modsel[2] = MODSEL_QSFP(X+2) */
+                        {0, 1, 7}, /* map_modsel[3] = MODSEL_QSFP(X+3) */
+                        {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP(X+4) */
+                        {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP(X+5) */
+                        {1, 1, 6}, /* map_modsel[6] = MODSEL_QSFP(X+6) */
+                        {1, 1, 7}, /* map_modsel[7] = MODSEL_QSFP(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_cypress_nabc = {
+
+    .chip_amount = 3,
+    .data_width  = 2,
+
+    .map_present    = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X)   */
+                        {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+                        {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+                        {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+                        {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */
+                        {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */
+                        {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */
+                        {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */
+    },
+    .map_tx_fault   = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X)   */
+                        {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+                        {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+                        {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+                        {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */
+                        {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */
+                        {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */
+                        {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */
+    },
+    .map_rxlos      = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X)   */
+                        {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+                        {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+                        {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+                        {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */
+                        {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */
+                        {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */
+                        {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */
+    },
+    .map_hard_rs0   = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X)   */
+                        {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */
+                        {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */
+                        {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */
+                        {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */
+                        {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */
+                        {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */
+                        {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */
+    },
+    .map_hard_rs1   = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X)   */
+                        {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */
+                        {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */
+                        {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */
+                        {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */
+                        {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */
+                        {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */
+                        {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_cypress_7abc = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {2, 0, 0}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {2, 0, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {2, 0, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {2, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {2, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {2, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+    },
+    .map_reset      = { {0, 0, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X)   */
+                        {0, 0, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+                        {0, 0, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+                        {0, 0, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */
+                        {0, 0, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */
+                        {0, 0, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */
+    },
+    .map_lpmod      = { {0, 1, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X)   */
+                        {0, 1, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+                        {0, 1, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+                        {0, 1, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */
+                        {0, 1, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */
+                        {0, 1, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */
+    },
+    .map_modsel     = { {1, 1, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X)   */
+                        {1, 1, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+                        {1, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+                        {1, 1, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */
+                        {1, 1, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */
+                        {1, 1, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_tahoe_5a = {
+
+    .chip_amount    = 1,
+    .data_width     = 2,
+
+    .map_present    = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+    },
+    .map_reset      = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X)   */
+                        {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+                        {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+    },
+    .map_lpmod      = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X)   */
+                        {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+                        {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+    },
+    .map_modsel     = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X)   */
+                        {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+                        {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_tahoe_6abc = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {0, 0, 3}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {0, 1, 0}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {0, 1, 5}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {1, 0, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {1, 1, 0}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {1, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {2, 0, 3}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {2, 1, 0}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+                        {2, 1, 5}, /* map_present[8] = MOD_ABS_PORT(X+8) */
+    },
+    .map_reset      = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP28_N_P(X)   */
+                        {0, 0, 6}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+                        {0, 1, 3}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+                        {1, 0, 1}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+                        {1, 0, 6}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+                        {1, 1, 3}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+                        {2, 0, 1}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+                        {2, 0, 6}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+                        {2, 1, 3}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+    },
+    .map_lpmod      = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP28_P(X)   */
+                        {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+                        {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+                        {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+                        {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+                        {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+                        {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+                        {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+                        {2, 1, 4}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+8) */
+    },
+    .map_modsel     = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X)   */
+                        {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+                        {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+                        {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+                        {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+                        {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+                        {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+                        {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+                        {2, 1, 2}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_sequoia_nabc = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_reset      = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP28_N_P(X)   */
+                        {0, 1, 1}, /* map_reset[1] = QRESET_QSFP28_N_P(X+1) */
+                        {0, 1, 2}, /* map_reset[2] = QRESET_QSFP28_N_P(X+2) */
+                        {0, 1, 3}, /* map_reset[3] = QRESET_QSFP28_N_P(X+3) */
+                        {0, 1, 4}, /* map_reset[4] = QRESET_QSFP28_N_P(X+4) */
+                        {0, 1, 5}, /* map_reset[5] = QRESET_QSFP28_N_P(X+5) */
+                        {0, 1, 6}, /* map_reset[6] = QRESET_QSFP28_N_P(X+6) */
+                        {0, 1, 7}, /* map_reset[7] = QRESET_QSFP28_N_P(X+7) */
+    },
+    .map_lpmod      = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP28_P(X)   */
+                        {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP28_P(X+1) */
+                        {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP28_P(X+2) */
+                        {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP28_P(X+3) */
+                        {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP28_P(X+4) */
+                        {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP28_P(X+5) */
+                        {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP28_P(X+6) */
+                        {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP28_P(X+7) */
+    },
+    .map_modsel     = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP28_N_P(X)   */
+                        {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP28_N_P(X+1) */
+                        {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP28_N_P(X+2) */
+                        {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP28_N_P(X+3) */
+                        {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP28_N_P(X+4) */
+                        {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP28_N_P(X+5) */
+                        {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP28_N_P(X+6) */
+                        {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP28_N_P(X+7) */
+    },
+};
+
+
+struct ioexp_map_s ioexp_map_lavender_p65 = {
+
+    .chip_amount    = 1,
+    .data_width     = 1,
+
+    .map_present    = { {0, 0, 4}, }, /* map_present[0] = MOD_ABS_PORT(X)      */
+    .map_reset      = { {0, 0, 1}, }, /* map_reset[0]   = QRESET_QSFP28_N_P(X) */
+    .map_lpmod      = { {0, 0, 2}, }, /* map_lpmod[0]   = LPMODE_QSFP28_P(X)   */
+    .map_modsel     = { {0, 0, 0}, }, /* map_modsel[0]  = MODSEL_QSFP28_N_P(X) */
+};
+
+
+struct ioexp_map_s cpld_map_cottonwood = {
+
+    .chip_amount = 1,
+    .data_width  = 4,
+
+    .map_present    = { {0, 2, 0}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {0, 2, 4}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {0, 3, 0}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {0, 3, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+    },
+    .map_tx_disable = { {0, 0, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X)   */
+                        {0, 0, 4}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+                        {0, 1, 0}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+                        {0, 1, 4}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+    },
+    .map_tx_fault   = { {0, 2, 2}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X)   */
+                        {0, 2, 6}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+                        {0, 3, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+                        {0, 3, 6}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+    },
+    .map_rxlos      = { {0, 2, 1}, /* map_rxlos[0] = OPRXLOS_PORT(X)   */
+                        {0, 2, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+                        {0, 3, 1}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+                        {0, 3, 5}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+    },
+    .map_hard_rs0   = { {0, 0, 2}, /* map_hard_rs0[0] = RS0_SFP28_P(X)   */
+                        {0, 0, 6}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */
+                        {0, 1, 2}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */
+                        {0, 1, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */
+    },
+    .map_hard_rs1   = { {0, 0, 2}, /* map_hard_rs1[0] = RS1_SFP28_P(X)   */
+                        {0, 0, 6}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */
+                        {0, 1, 2}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */
+                        {0, 1, 6}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */
+    },
+};
+
+struct ioexp_map_s ioexp_map_maple_0abc = {
+
+    .chip_amount    = 3,
+    .data_width     = 2,
+
+    .map_present    = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {2, 1, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {2, 1, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_reset      = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X)   */
+                        {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */
+                        {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */
+                        {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */
+                        {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */
+                        {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */
+                        {0, 1, 6}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */
+                        {0, 1, 7}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */
+    },
+    .map_lpmod      = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X)   */
+                        {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */
+                        {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */
+                        {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */
+                        {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */
+                        {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */
+                        {1, 0, 6}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */
+                        {1, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */
+    },
+    .map_modsel     = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X)   */
+                        {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */
+                        {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */
+                        {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */
+                        {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */
+                        {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */
+                        {0, 0, 6}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */
+                        {0, 0, 7}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */
+    },
+};
+
+struct ioexp_map_s ioexp_map_maple_nabc = {
+
+    .chip_amount = 3,
+    .data_width  = 2,
+
+    .map_present    = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X)   */
+                        {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */
+                        {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */
+                        {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */
+                        {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */
+                        {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */
+                        {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */
+                        {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */
+    },
+    .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X)   */
+                        {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */
+                        {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */
+                        {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */
+                        {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */
+                        {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */
+                        {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */
+                        {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */
+    },
+    .map_tx_fault   = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X)   */
+                        {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */
+                        {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */
+                        {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */
+                        {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */
+                        {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */
+                        {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */
+                        {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */
+    },
+    .map_rxlos      = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X)   */
+                        {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */
+                        {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */
+                        {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */
+                        {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */
+                        {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */
+                        {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */
+                        {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */
+    },
+    .map_hard_rs0   = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X)   */
+                        {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */
+                        {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */
+                        {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */
+                        {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */
+                        {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */
+                        {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */
+                        {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */
+    },
+    .map_hard_rs1   = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X)   */
+                        {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */
+                        {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */
+                        {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */
+                        {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */
+                        {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */
+                        {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */
+                        {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */
+    },
+};
+
+/* ========== Private functions ==========
+ */
+int check_channel_tier_1(void);
+
+struct i2c_client *
+_get_i2c_client(struct ioexp_obj_s *self,
+                int chip_id){
+
+    struct ioexp_i2c_s *i2c_curr_p = self->i2c_head_p;
+
+    if (!(i2c_curr_p)){
+        SWPS_ERR("%s: i2c_curr_p is NULL\n", __func__);
+        return NULL;
+    }
+    while (i2c_curr_p){
+        if ((i2c_curr_p->chip_id) == chip_id){
+            return i2c_curr_p->i2c_client_p;
+        }
+        i2c_curr_p = i2c_curr_p->next;
+    }
+    SWPS_ERR("%s: not exist! <chip_id>:%d\n", __func__, chip_id);
+    return NULL;
+}
+
+
+static int
+_common_ioexp_update_one(struct ioexp_obj_s *self,
+                         struct ioexp_addr_s *ioexp_addr,
+                         int chip_id,
+                         int data_width,
+                         int show_err,
+                         char *caller_name) {
+    int buf      = 0;
+    int err      = 0;
+    int data_id  = 0;
+    int r_offset = 0;
+
+    for(data_id=0; data_id<data_width; data_id++){
+        /* Read from IOEXP */
+        r_offset = ioexp_addr->read_offset[data_id];
+        buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), r_offset);
+        /* Check error */
+        if (buf < 0) {
+            err = 1;
+            if (show_err) {
+                SWPS_INFO("IOEXP-%d read fail! <err>:%d \n", self->ioexp_id, buf);
+                SWPS_INFO("Dump: <chan>:%d <addr>:0x%02x <offset>:%d, <caller>:%s\n",
+                          ioexp_addr->chan_id, ioexp_addr->chip_addr,
+                          ioexp_addr->read_offset[data_id], caller_name);
+            }
+            continue;
+        }
+        /* Update IOEXP object */
+        self->chip_data[chip_id].data[data_id] = (uint8_t)buf;
+    }
+    if (err) {
+        return ERR_IOEXP_UNEXCPT;
+    }
+    return 0;
+}
+
+
+static int
+common_ioexp_update_all(struct ioexp_obj_s *self,
+                        int show_err,
+                        char *caller_name){
+
+    int err     = 0;
+    int chip_id = 0;
+    int chip_amount = self->ioexp_map_p->chip_amount;
+
+    for (chip_id=0; chip_id<chip_amount; chip_id++){
+        if (_common_ioexp_update_one(self,
+                                     &(self->ioexp_map_p->map_addr[chip_id]),
+                                     chip_id,
+                                     self->ioexp_map_p->data_width,
+                                     show_err,
+                                     caller_name) < 0) {
+            err = 1;
+        }
+    }
+    if (err) {
+        return ERR_IOEXP_UNEXCPT;
+    }
+    return 0;
+}
+
+
+static int
+_common_check_by_mode(struct ioexp_obj_s *self){
+
+    switch (self->mode){
+        case IOEXP_MODE_DIRECT:
+            return self->fsm_4_direct(self);
+
+        case IOEXP_MODE_POLLING:
+            if (self->state >= 0){
+                return 0;
+            }
+            switch (self->state){
+                case STATE_IOEXP_INIT:
+                    return ERR_IOEXP_UNINIT;
+                case STATE_IOEXP_ABNORMAL:
+                    return ERR_IOEXP_ABNORMAL;
+                default:
+                    return ERR_IOEXP_NOSTATE;
+            }
+            break;
+
+        default:
+            break;
+    }
+    SWPS_ERR("%s: Exception occurs. <mode>:%d \n", __func__, self->mode);
+    return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+_common_get_bit(struct ioexp_obj_s *self,
+                struct ioexp_bitmap_s *bitmap_obj_p,
+                char *func_mane){
+    uint8_t buf;
+    int err_code;
+
+    /* Check and get address */
+    err_code = _common_check_by_mode(self);
+    if (err_code < 0){
+        return err_code;
+    }
+    if (!bitmap_obj_p){
+        SWPS_ERR("Layout config incorrect! <ioexp_id>:%d <func>:%s\n",
+                 self->ioexp_id, func_mane);
+        return ERR_IOEXP_BADCONF;
+    }
+    /* Get data form cache */
+    buf = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+    return (int)(buf >> bitmap_obj_p->bit_shift & 0x01);
+}
+
+
+static int
+_common_set_bit(struct ioexp_obj_s *self,
+                struct ioexp_bitmap_s *bitmap_obj_p,
+                int input_val,
+                char *func_mane){
+    int err_code, target_offset;
+    uint8_t origin_byte;
+    uint8_t modify_byte;
+
+    /* Check and get address */
+    err_code = _common_check_by_mode(self);
+    if (err_code < 0){
+        return err_code;
+    }
+    if (!bitmap_obj_p){
+        SWPS_ERR("Layout config incorrect! <ioexp>:%d <func>:%s\n",
+                 self->ioexp_id, func_mane);
+        return ERR_IOEXP_BADCONF;
+    }
+    /* Prepare write date */
+    origin_byte = self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset];
+    switch (input_val) {
+        case 0:
+            modify_byte = origin_byte;
+            SWP_BIT_CLEAR(modify_byte, bitmap_obj_p->bit_shift);
+            break;
+        case 1:
+            modify_byte = origin_byte;
+            SWP_BIT_SET(modify_byte, bitmap_obj_p->bit_shift);
+            break;
+        default:
+            SWPS_ERR("Input value incorrect! <val>:%d <ioexp>:%d <func>:%s\n",
+                     input_val, self->ioexp_id, func_mane);
+            return ERR_IOEXP_BADINPUT;
+    }
+    /* Setup i2c client */
+    target_offset = self->ioexp_map_p->map_addr[bitmap_obj_p->chip_id].write_offset[bitmap_obj_p->ioexp_voffset];
+    /* Write byte to chip via I2C */
+    err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, bitmap_obj_p->chip_id),
+                                         target_offset,
+                                         modify_byte);
+    /* Update or bollback object */
+    if (err_code < 0){
+        self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = origin_byte;
+        SWPS_ERR("I2C write fail! <input>:%d <ioexp>:%d <func>:%s <err>:%d\n",
+                 input_val, self->ioexp_id, func_mane, err_code);
+        return err_code;
+    }
+    self->chip_data[bitmap_obj_p->chip_id].data[bitmap_obj_p->ioexp_voffset] = modify_byte;
+    return 0;
+}
+
+
+/* ========== Object public functions ==========
+ */
+int
+common_get_present(struct ioexp_obj_s *self,
+                   int virt_offset){
+
+    int UNPLUG = 1;
+    int retval = ERR_IOEXP_UNEXCPT;
+
+    retval = _common_get_bit(self,
+                             &(self->ioexp_map_p->map_present[virt_offset]),
+                             "common_get_present");
+    if (retval < 0) {
+        /* [Note]
+         * => Transceiver object does not need to handle IOEXP layer issues.
+         */
+        return UNPLUG;
+    }
+    return retval;
+}
+
+
+int
+common_get_tx_fault(struct ioexp_obj_s *self,
+                    int virt_offset){
+    /* [Transmit Fault (Tx_Fault)]
+     * A catastrophic laser fault will activate the transmitter signal,
+     * TX_FAULT, and disable the laser. This signal is an open collector
+     * output (pull-up required on the host board). A low signal indicates
+     * normal laser operation and a high signal indicates a fault. The
+     * TX_FAULT will be latched high when a laser fault occurs and is
+     * cleared by toggling the TX_DISABLE input or power cycling the
+     * transceiver. The transmitter fault condition can also be monitored
+     * via the two-wire serial interface.
+     * (address A2, byte 110, bit 2).
+     *
+     * 0: Normal
+     * 1: Abnormal
+     */
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_tx_fault[virt_offset]),
+                           "common_get_tx_fault");
+}
+
+
+int
+common_get_rxlos(struct ioexp_obj_s *self,
+                 int virt_offset){
+    /* [Receiver Loss of Signal (Rx_LOS)]
+     * The post-amplification IC also includes transition detection circuitry
+     * which monitors the ac level of incoming optical signals and provides a
+     * TTL/CMOS compatible status signal to the host (pin 8). An adequate optical
+     * input results in a low Rx_LOS output while a high Rx_LOS output indicates
+     * an unusable optical input. The Rx_LOS thresholds are factory set so that
+     * a high output indicates a definite optical fault has occurred. Rx_LOS can
+     * also be monitored via the two-wire serial interface
+     * (address A2h, byte 110, bit 1).
+     *
+     * 0: Normal
+     * 1: Abnormal
+     */
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_rxlos[virt_offset]),
+                           "common_get_rxlos");
+}
+
+
+int
+common_get_tx_disable(struct ioexp_obj_s *self,
+                      int virt_offset){
+
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_tx_disable[virt_offset]),
+                           "common_get_tx_disable");
+}
+
+
+int
+common_get_reset(struct ioexp_obj_s *self,
+                 int virt_offset){
+
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_reset[virt_offset]),
+                           "common_get_reset");
+}
+
+
+int
+common_get_lpmod(struct ioexp_obj_s *self,
+                 int virt_offset){
+
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_lpmod[virt_offset]),
+                           "common_get_lpmod");
+}
+
+
+int
+common_get_modsel(struct ioexp_obj_s *self,
+                  int virt_offset){
+
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_modsel[virt_offset]),
+                           "common_get_modsel");
+}
+
+
+int
+common_get_hard_rs0(struct ioexp_obj_s *self,
+                    int virt_offset){
+
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_hard_rs0[virt_offset]),
+                           "common_get_hard_rs0");
+}
+
+
+int
+common_get_hard_rs1(struct ioexp_obj_s *self,
+                   int virt_offset){
+
+    return _common_get_bit(self,
+                           &(self->ioexp_map_p->map_hard_rs1[virt_offset]),
+                           "common_get_hard_rs1");
+}
+
+
+int
+common_set_tx_disable(struct ioexp_obj_s *self,
+                      int virt_offset,
+                      int input_val){
+
+    return _common_set_bit(self,
+                           &(self->ioexp_map_p->map_tx_disable[virt_offset]),
+                           input_val,
+                           "common_set_tx_disable");
+}
+
+
+int
+common_set_reset(struct ioexp_obj_s *self,
+                 int virt_offset,
+                 int input_val){
+
+    return _common_set_bit(self,
+                           &(self->ioexp_map_p->map_reset[virt_offset]),
+                           input_val,
+                           "common_set_reset");
+}
+
+
+int
+common_set_lpmod(struct ioexp_obj_s *self,
+                 int virt_offset,
+                 int input_val){
+
+    return _common_set_bit(self,
+                           &(self->ioexp_map_p->map_lpmod[virt_offset]),
+                           input_val,
+                           "common_set_lpmod");
+}
+
+
+int
+common_set_modsel(struct ioexp_obj_s *self,
+                  int virt_offset,
+                  int input_val){
+
+    return _common_set_bit(self,
+                           &(self->ioexp_map_p->map_modsel[virt_offset]),
+                           input_val,
+                           "common_set_modsel");
+}
+
+
+int
+common_set_hard_rs0(struct ioexp_obj_s *self,
+        int virt_offset,
+        int input_val){
+
+    return _common_set_bit(self,
+                           &(self->ioexp_map_p->map_hard_rs0[virt_offset]),
+                           input_val,
+                           "common_set_hard_rs0");
+}
+
+
+int
+common_set_hard_rs1(struct ioexp_obj_s *self,
+        int virt_offset,
+        int input_val){
+
+    return _common_set_bit(self,
+                           &(self->ioexp_map_p->map_hard_rs1[virt_offset]),
+                           input_val,
+                           "common_set_hard_rs1");
+}
+
+
+int
+ioexp_get_not_support(struct ioexp_obj_s *self,
+                      int virt_offset){
+    return ERR_IOEXP_NOTSUPPORT;
+}
+
+
+int
+ioexp_set_not_support(struct ioexp_obj_s *self,
+                      int virt_offset,
+                      int input_val){
+    return ERR_IOEXP_NOTSUPPORT;
+}
+
+
+int
+fake_ioexp_init(struct ioexp_obj_s *self){
+    return 1;
+}
+
+int
+fake_ioexp_update(struct ioexp_obj_s *self){
+    return 1;
+}
+
+
+int
+fake_update_func(struct ioexp_obj_s *self){
+    return 1;
+}
+
+int
+fake_get_func(struct ioexp_obj_s *self,
+              int virt_offset){
+    SWPS_WARN("Someone called fake_get_func\n");
+    return -1;
+}
+
+int
+fake_set_func(struct ioexp_obj_s *self,
+              int virt_offset,
+              int input_val){
+    SWPS_WARN("Someone called fake_set_func\n");
+    return -1;
+}
+
+
+/* ========== Initial functions for IO Expander ==========
+ */
+int
+common_ioexp_init(struct ioexp_obj_s *self) {
+
+    int chip_id, offset, err_code;
+    struct ioexp_addr_s *addr_p;
+    
+    if (self->mode == IOEXP_MODE_DIRECT) {
+        goto update_common_ioexp_init;
+    }
+    /* Setup default value to each physical IO Expander */
+    for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+        /* Get address mapping */
+        addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+        if (!addr_p){
+            SWPS_ERR("%s: IOEXP config incorrect! <chip_id>:%d \n",
+                     __func__, chip_id);
+            return -1;
+        }
+        /* Setup default value */
+        for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+            
+            /* [Desc] Skip the setup default value behavior
+               [Note] Setup default value = -1 if you don't want to write the value to IOEXP or CPLD
+            */
+            if(addr_p->write_offset[offset] < 0){ 
+                SWPS_DEBUG("skip a write_offset <%d>\n", addr_p->conf_offset[offset]);
+                continue;
+            }
+            err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+                                                 addr_p->write_offset[offset],
+                                                 addr_p->data_default[offset]);
+            if (err_code < 0){
+                SWPS_ERR("%s: set default fail! <error>:%d \n",
+                         __func__, err_code);
+                return ERR_IOEXP_UNEXCPT;
+            }
+        }
+    }
+update_common_ioexp_init:
+    /* Check and update info to object */
+    err_code = self->update_all(self, 1, "common_ioexp_init");
+    if (err_code < 0) {
+        SWPS_ERR("%s: update_all() fail! <error>:%d \n",
+                __func__, err_code);
+        return ERR_IOEXP_UNEXCPT;
+    }
+    return 0;
+}
+
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+_is_channel_ready(struct ioexp_obj_s *self){
+
+    int buf     = 0;
+    int chip_id = 0;  /* Use first chip which be registered */
+    int data_id = 0;  /* Use first byte which be registered */
+    struct ioexp_addr_s *ioexp_addr = NULL;
+
+    ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]);
+    if (!ioexp_addr){
+        SWPS_ERR("%s: config incorrect!\n", __func__);
+        return ERR_IOEXP_UNEXCPT;
+    }
+    buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id),
+                                   ioexp_addr->read_offset[data_id]);
+    if (buf >= 0){
+        return 1;
+    }
+    return 0;
+}
+
+int
+_ioexp_init_handler(struct ioexp_obj_s *self){
+
+    int return_val;
+
+    switch (self->mode) {
+        case IOEXP_MODE_DIRECT:
+            return_val = self->init(self);
+            if (return_val < 0){
+                self->state = STATE_IOEXP_ABNORMAL;
+            } else {
+                self->state = STATE_IOEXP_NORMAL;
+            }
+            return return_val;
+
+        case IOEXP_MODE_POLLING:
+            /* Check system and channel is ready */
+            if (self->state == STATE_IOEXP_INIT){
+                if (!_is_channel_ready(self)){
+                    self->state = STATE_IOEXP_INIT;
+                    SWPS_WARN("%s: IOEXP:%d channel not ready.\n",
+                            __func__, self->ioexp_id);
+                    return 0;
+                }
+            }
+            /* Execute initial callback */
+            return_val = self->init(self);
+            if (return_val < 0){
+                self->state = STATE_IOEXP_ABNORMAL;
+            } else {
+                self->state = STATE_IOEXP_NORMAL;
+            }
+            return return_val;
+
+        default:
+            break;
+    }
+    SWPS_ERR("%s: exception occur <mode>:%d\n", __func__, self->mode);
+    return ERR_IOEXP_UNEXCPT;
+}
+
+
+int
+common_ioexp_fsm_4_direct(struct ioexp_obj_s *self){
+
+    int result_val;
+    int show_err = 1;
+    char *func_mane = "common_ioexp_fsm_4_direct";
+
+    switch (self->state){
+        case STATE_IOEXP_INIT:
+            result_val = _ioexp_init_handler(self);
+            /* Exception case: terminate initial procedure */
+            if(result_val < 0){
+                /* Initial fail */
+                return result_val;
+            }
+            if(self->state == STATE_IOEXP_INIT){
+                /* Keep in INIT state, and return error */
+                return ERR_IOEXP_UNINIT;
+            }
+            /* Case: Initial done */
+            return 0;
+
+        case STATE_IOEXP_NORMAL:
+            result_val = self->update_all(self, show_err, func_mane);
+            if (result_val < 0){
+                SWPS_INFO("%s: NORMAL -> ABNORMAL <err>:%d\n",
+                           __func__, result_val);
+                self->state = STATE_IOEXP_ABNORMAL;
+                return result_val;
+            }
+            self->state = STATE_IOEXP_NORMAL;
+            return 0;
+
+        case STATE_IOEXP_ABNORMAL:
+            result_val = self->update_all(self, show_err, func_mane);
+            if (result_val < 0){
+                self->state = STATE_IOEXP_ABNORMAL;
+                return result_val;
+            }
+            SWPS_DEBUG("%s: ABNORMAL -> NORMAL <err>:%d\n",
+                       __func__, result_val);
+            self->state = STATE_IOEXP_NORMAL;
+            return 0;
+
+        default:
+            break;
+    }
+    SWPS_ERR("%s: Exception occurs <state>:%d\n",
+            __func__, self->state);
+    return ERR_IOEXP_UNEXCPT;
+}
+
+
+int
+common_ioexp_fsm_4_polling(struct ioexp_obj_s *self){
+
+    int result_val, i, show_e;
+    int fail_retry = 3;
+    char *func_name = "common_ioexp_fsm_4_polling";
+
+#ifdef DEBUG_SWPS
+    show_e = 1;
+#else
+    show_e = 0;
+#endif
+
+    switch (self->state){
+        case STATE_IOEXP_INIT:
+            result_val = _ioexp_init_handler(self);
+            /* Exception case: terminate initial procedure */
+            if(result_val < 0){
+                /* Initial fail */
+                return result_val;
+            }
+            /* Case: System (Channel) not ready */
+            if(self->state == STATE_IOEXP_INIT){
+                /* Keep in INIT state, wait and retry */
+                return 0;
+            }
+            /* Case: Initial done */
+            SWPS_INFO("IOEXP-%d: initial done. <type>:%d\n",
+                      self->ioexp_id, self->ioexp_type);
+            return result_val;
+
+        case STATE_IOEXP_NORMAL:
+            /* Retry mechanism for case of i2c topology not stable */
+            for (i=0; i<fail_retry; i++) {
+                result_val = self->update_all(self, show_e, func_name);
+                if (result_val >= 0) {
+                    self->state = STATE_IOEXP_NORMAL;
+                    return 0;
+                }
+                if (check_channel_tier_1() < 0) {
+                    SWPS_INFO("%s: detect I2C crash <ioexp>:%d\n",
+                              __func__, self->ioexp_id);
+                    break;
+                }
+                SWPS_DEBUG("IOEXP-%d: unstable <retry>:%d\n",
+                           self->ioexp_id, result_val);
+            }
+            SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL <err>:%d\n",
+                      self->ioexp_id, result_val);
+            self->state = STATE_IOEXP_ABNORMAL;
+            return result_val;
+
+        case STATE_IOEXP_ABNORMAL:
+            result_val = self->update_all(self, show_e, func_name);
+            if (result_val < 0){
+                self->state = STATE_IOEXP_ABNORMAL;
+                return result_val;
+            }
+            SWPS_INFO("IOEXP-%d: ABNORMAL -> NORMAL <err>:%d\n",
+                      self->ioexp_id, result_val);
+            self->state = STATE_IOEXP_NORMAL;
+            return 0;
+
+        default:
+            break;
+    }
+    SWPS_ERR("IOEXP-%d: Exception occurs <state>:%d\n",
+             self->ioexp_id, self->state);
+    return ERR_IOEXP_UNEXCPT;
+}
+
+
+/* ========== Object private functions for check & update ==========
+ */
+int
+common_ioexp_check(struct ioexp_obj_s *self){
+
+    int result;
+
+    if (self->mode != IOEXP_MODE_POLLING){
+        SWPS_ERR("%s: not polling mode <mode>:%d\n",
+                 __func__, self->mode);
+        return ERR_IOEXP_NOTSUPPORT;
+    }
+    mutex_lock(&self->lock);
+    result = self->fsm_4_polling(self);
+    mutex_unlock(&self->lock);
+    return result;
+}
+
+
+/* ========== Functions for Factory pattern ==========
+ */
+static struct ioexp_map_s *
+get_ioexp_map(int ioexp_type){
+    switch (ioexp_type){
+        case IOEXP_TYPE_MAGINOLIA_NAB:
+            return &ioexp_map_magnolia_nab;
+        case IOEXP_TYPE_MAGINOLIA_4AB:
+            return &ioexp_map_magnolia_4ab;
+        case IOEXP_TYPE_MAGINOLIA_7AB:
+        case IOEXP_TYPE_SPRUCE_7AB:
+            return &ioexp_map_magnolia_7ab;
+        case IOEXP_TYPE_REDWOOD_P01P08:
+            return &ioexp_map_redwood_p01p08_p17p24;
+        case IOEXP_TYPE_REDWOOD_P09P16:
+            return &ioexp_map_redwood_p09p16_p25p32;
+        case IOEXP_TYPE_HUDSON32IGA_P01P08:
+            return &ioexp_map_hudson32iga_p01p08_p17p24;
+        case IOEXP_TYPE_HUDSON32IGA_P09P16:
+            return &ioexp_map_hudson32iga_p09p16_p25p32;
+        case IOEXP_TYPE_CYPRESS_NABC:
+            return &ioexp_map_cypress_nabc;
+        case IOEXP_TYPE_CYPRESS_7ABC:
+            return &ioexp_map_cypress_7abc;
+        case IOEXP_TYPE_TAHOE_5A:
+            return &ioexp_map_tahoe_5a;
+        case IOEXP_TYPE_TAHOE_6ABC:
+            return &ioexp_map_tahoe_6abc;
+        case IOEXP_TYPE_SEQUOIA_NABC:
+            return &ioexp_map_sequoia_nabc;
+        case IOEXP_TYPE_LAVENDER_P65:
+            return &ioexp_map_lavender_p65;
+        case CPLD_TYPE_COTTONWOOD:
+            return &cpld_map_cottonwood;
+        case IOEXP_TYPE_MAPLE_0ABC:
+            return &ioexp_map_maple_0abc;
+        case IOEXP_TYPE_MAPLE_NABC:
+            return &ioexp_map_maple_nabc;
+        default:
+            return NULL;
+    }
+}
+
+
+int
+setup_ioexp_ssize_attr(struct ioexp_obj_s *self,
+                       struct ioexp_map_s *ioexp_map_p,
+                       int ioexp_id,
+                       int ioexp_type,
+                       int run_mode){
+    switch (run_mode){
+        case IOEXP_MODE_POLLING:  /* Direct access device mode */
+        case IOEXP_MODE_DIRECT:   /* Polling mode, read from cache */
+            self->mode = run_mode;
+            break;
+        default:
+            SWPS_ERR("%s: non-defined run_mode:%d\n",
+                     __func__, run_mode);
+            self->mode = ERR_IOEXP_UNEXCPT;
+            return ERR_IOEXP_UNEXCPT;
+    }
+    /* Setup mapping structure */
+    self->ioexp_map_p = kzalloc(sizeof(*ioexp_map_p), GFP_KERNEL);
+    if (!(self->ioexp_map_p)) {
+        SWPS_ERR("%s: kzalloc ioexp_map_p fail\n", __func__);
+        return -1;
+    }
+    memcpy(self->ioexp_map_p, ioexp_map_p, sizeof(*ioexp_map_p));
+    /* Setup attributes */
+    self->ioexp_id   = ioexp_id;
+    self->ioexp_type = ioexp_type;
+    self->state      = STATE_IOEXP_INIT;
+    mutex_init(&self->lock);
+    return 0;
+}
+
+
+static int
+setup_addr_mapping(struct ioexp_obj_s *self,
+                   struct ioexp_addr_s *addr_map_p,
+                   int chip_amount){
+    struct ioexp_addr_s *tmp_p;
+    if (!addr_map_p){
+        SWPS_ERR("%s: map is null\n", __func__);
+        return -1;
+    }
+    tmp_p = kzalloc((sizeof(*addr_map_p) * chip_amount), GFP_KERNEL);
+    if (!tmp_p){
+        SWPS_ERR("%s: kzalloc fail.\n", __func__);
+        return -1;
+    }
+    memcpy(tmp_p, addr_map_p, (sizeof(*addr_map_p) * chip_amount));
+    self->ioexp_map_p->map_addr = tmp_p;
+
+    return 0;
+}
+
+
+static int
+setup_ioexp_public_cb(struct ioexp_obj_s *self,
+                      int ioexp_type){
+
+    switch (ioexp_type){
+        case IOEXP_TYPE_MAGINOLIA_NAB:
+        case IOEXP_TYPE_MAGINOLIA_4AB:
+        case CPLD_TYPE_COTTONWOOD:
+            self->get_present    = common_get_present;
+            self->get_tx_fault   = common_get_tx_fault;
+            self->get_rxlos      = common_get_rxlos;
+            self->get_tx_disable = common_get_tx_disable;
+            self->get_reset      = ioexp_get_not_support;
+            self->get_lpmod      = ioexp_get_not_support;
+            self->get_modsel     = ioexp_get_not_support;
+            self->get_hard_rs0   = ioexp_get_not_support;
+            self->get_hard_rs1   = ioexp_get_not_support;
+            self->set_tx_disable = common_set_tx_disable;
+            self->set_reset      = ioexp_set_not_support;
+            self->set_lpmod      = ioexp_set_not_support;
+            self->set_modsel     = ioexp_set_not_support;
+            self->set_hard_rs0   = ioexp_set_not_support;
+            self->set_hard_rs1   = ioexp_set_not_support;
+            return 0;
+        case IOEXP_TYPE_CYPRESS_NABC:
+        case IOEXP_TYPE_MAPLE_NABC:
+            self->get_present    = common_get_present;
+            self->get_tx_fault   = common_get_tx_fault;
+            self->get_rxlos      = common_get_rxlos;
+            self->get_tx_disable = common_get_tx_disable;
+            self->get_reset      = ioexp_get_not_support;
+            self->get_lpmod      = ioexp_get_not_support;
+            self->get_modsel     = ioexp_get_not_support;
+            self->get_hard_rs0   = common_get_hard_rs0;
+            self->get_hard_rs1   = common_get_hard_rs1;
+            self->set_tx_disable = common_set_tx_disable;
+            self->set_reset      = ioexp_set_not_support;
+            self->set_lpmod      = ioexp_set_not_support;
+            self->set_modsel     = ioexp_set_not_support;
+            self->set_hard_rs0   = common_set_hard_rs0;
+            self->set_hard_rs1   = common_set_hard_rs1;
+            return 0;
+        case IOEXP_TYPE_MAGINOLIA_7AB:
+        case IOEXP_TYPE_SPRUCE_7AB:
+        case IOEXP_TYPE_REDWOOD_P01P08:
+        case IOEXP_TYPE_REDWOOD_P09P16:
+        case IOEXP_TYPE_HUDSON32IGA_P01P08:
+        case IOEXP_TYPE_HUDSON32IGA_P09P16:
+        case IOEXP_TYPE_CYPRESS_7ABC:
+        case IOEXP_TYPE_TAHOE_5A:
+        case IOEXP_TYPE_TAHOE_6ABC:
+        case IOEXP_TYPE_SEQUOIA_NABC:
+        case IOEXP_TYPE_LAVENDER_P65:
+        case IOEXP_TYPE_MAPLE_0ABC:
+            self->get_present    = common_get_present;
+            self->get_tx_fault   = ioexp_get_not_support;
+            self->get_rxlos      = ioexp_get_not_support;
+            self->get_tx_disable = ioexp_get_not_support;
+            self->get_reset      = common_get_reset;
+            self->get_lpmod      = common_get_lpmod;
+            self->get_modsel     = common_get_modsel;
+            self->get_hard_rs0   = ioexp_get_not_support;
+            self->get_hard_rs1   = ioexp_get_not_support;
+            self->set_tx_disable = ioexp_set_not_support;
+            self->set_reset      = common_set_reset;
+            self->set_lpmod      = common_set_lpmod;
+            self->set_modsel     = common_set_modsel;
+            self->set_hard_rs0   = ioexp_set_not_support;
+            self->set_hard_rs1   = ioexp_set_not_support;
+            return 0;
+
+        default:
+            SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+            break;
+    }
+    return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_ioexp_private_cb(struct ioexp_obj_s *self,
+                       int ioexp_type){
+
+    switch (ioexp_type){
+        case IOEXP_TYPE_MAGINOLIA_NAB:
+        case IOEXP_TYPE_MAGINOLIA_4AB:
+        case IOEXP_TYPE_MAGINOLIA_7AB:
+        case IOEXP_TYPE_SPRUCE_7AB:
+        case IOEXP_TYPE_REDWOOD_P01P08:
+        case IOEXP_TYPE_REDWOOD_P09P16:
+        case IOEXP_TYPE_HUDSON32IGA_P01P08:
+        case IOEXP_TYPE_HUDSON32IGA_P09P16:
+        case IOEXP_TYPE_CYPRESS_NABC:
+        case IOEXP_TYPE_CYPRESS_7ABC:
+        case IOEXP_TYPE_TAHOE_5A:
+        case IOEXP_TYPE_TAHOE_6ABC:
+        case IOEXP_TYPE_SEQUOIA_NABC:
+        case IOEXP_TYPE_LAVENDER_P65:
+        case CPLD_TYPE_COTTONWOOD:
+        case IOEXP_TYPE_MAPLE_NABC:
+        case IOEXP_TYPE_MAPLE_0ABC:
+            self->init           = common_ioexp_init;
+            self->check          = common_ioexp_check;
+            self->update_all     = common_ioexp_update_all;
+            self->fsm_4_direct   = common_ioexp_fsm_4_direct;
+            self->fsm_4_polling  = common_ioexp_fsm_4_polling;
+            return 0;
+
+        default:
+            SWPS_ERR("%s: type:%d incorrect!\n", __func__, ioexp_type);
+            break;
+    }
+    return ERR_IOEXP_UNEXCPT;
+}
+
+
+static int
+setup_i2c_client_one(struct ioexp_obj_s *self,
+                     int chip_id){
+
+    char *err_msg = "ERROR";
+    struct i2c_adapter *adap    = NULL;
+    struct i2c_client  *client  = NULL;
+    struct ioexp_i2c_s *i2c_obj_p  = NULL;
+    struct ioexp_i2c_s *i2c_curr_p = NULL;
+
+    int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id;
+    adap = i2c_get_adapter(chan_id);
+    if(!adap){
+        err_msg = "Can not get adap!";
+        goto err_ioexp_setup_i2c_1;
+    }
+    client = kzalloc(sizeof(*client), GFP_KERNEL);
+    if (!client){
+        err_msg = "Can not kzalloc client!";
+        goto err_ioexp_setup_i2c_1;
+    }
+    i2c_obj_p = kzalloc(sizeof(*i2c_obj_p), GFP_KERNEL);
+    if (!i2c_obj_p){
+        err_msg = "Can not kzalloc i2c_obj_p!";
+        goto err_ioexp_setup_i2c_2;
+    }
+    client->adapter = adap;
+    client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr;
+    i2c_obj_p->i2c_client_p = client;
+    i2c_obj_p->chip_id = chip_id;
+    i2c_obj_p->next = NULL;
+    if (!self->i2c_head_p){
+        self->i2c_head_p = i2c_obj_p;
+    } else {
+        i2c_curr_p = self->i2c_head_p;
+        while (i2c_curr_p->next){
+            i2c_curr_p = i2c_curr_p->next;
+        }
+        i2c_curr_p->next = i2c_obj_p;
+    }
+    return 0;
+
+err_ioexp_setup_i2c_2:
+    kfree(client);
+err_ioexp_setup_i2c_1:
+    SWPS_ERR("%s: %s <chanID>:%d\n", __func__, err_msg, chan_id);
+    return -1;
+}
+
+
+static int
+setup_i2c_client(struct ioexp_obj_s* self){
+
+    int result;
+    int chip_id = 0;
+
+    for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+        result  = setup_i2c_client_one(self, chip_id);
+        if (result < 0){
+            SWPS_ERR("%s fail! <chip_id>:%d\n", __func__, chip_id);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+
+static int
+setup_ioexp_config(struct ioexp_obj_s *self) {
+
+    int chip_id, offset, err_code;
+    struct ioexp_addr_s *addr_p;
+
+    for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){
+        addr_p = &(self->ioexp_map_p->map_addr[chip_id]);
+        if (!addr_p){
+            SWPS_ERR("IOEXP config incorrect! <chip_id>:%d \n",chip_id);
+            return -1;
+        }
+        for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+            
+            /* [Desc] Skip the setup config value behavior
+               [Note] Setup config value = -1 if you don't want to write the value to IOEXP or CPLD
+            */
+            if(addr_p->conf_offset[offset] < 0){ 
+                SWPS_DEBUG("skip a config_offset <%d>\n", addr_p->conf_offset[offset]);
+                continue;
+            }
+            err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id),
+                                                 addr_p->conf_offset[offset],
+                                                 addr_p->conf_default[offset]);
+
+            if (err_code < 0){
+                SWPS_INFO("%s: set conf fail! <err>:%d \n", __func__, err_code);
+                return -2;
+            }
+        }
+    }
+    return 0;
+}
+
+
+struct ioexp_obj_s *
+_create_ioexp_obj(int ioexp_id,
+                  int ioexp_type,
+                  struct ioexp_addr_s *addr_map_p,
+                  int run_mode){
+
+    struct ioexp_map_s* ioexp_map_p;
+    struct ioexp_obj_s* result_p;
+    struct ioexp_i2c_s *i2c_curr_p;
+    struct ioexp_i2c_s *i2c_next_p;
+
+    /* Get layout */
+    ioexp_map_p = get_ioexp_map(ioexp_type);
+    if (!ioexp_map_p){
+        SWPS_ERR("%s: Invalid ioexp_type\n", __func__);
+        goto err_create_ioexp_fail;
+    }
+    /* Prepare IOEXP object */
+    result_p = kzalloc(sizeof(*result_p), GFP_KERNEL);
+    if (!result_p){
+        SWPS_ERR("%s: kzalloc failure!\n", __func__);
+        goto err_create_ioexp_fail;
+    }
+    /* Prepare static size attributes */
+    if (setup_ioexp_ssize_attr(result_p,
+                               ioexp_map_p,
+                               ioexp_id,
+                               ioexp_type,
+                               run_mode) < 0){
+        goto err_create_ioexp_setup_attr_fail;
+    }
+    /* Prepare address mapping */
+    if (setup_addr_mapping(result_p, addr_map_p, ioexp_map_p->chip_amount) < 0){
+        goto err_create_ioexp_setup_attr_fail;
+    }
+    if (setup_i2c_client(result_p) < 0){
+        goto err_create_ioexp_setup_i2c_fail;
+    }
+    /* Prepare call back functions of object */
+    if (setup_ioexp_public_cb(result_p, ioexp_type) < 0){
+        goto err_create_ioexp_setup_i2c_fail;
+    }
+    if (setup_ioexp_private_cb(result_p, ioexp_type) < 0){
+        goto err_create_ioexp_setup_i2c_fail;
+    }
+    return result_p;
+
+err_create_ioexp_setup_i2c_fail:
+    i2c_curr_p = result_p->i2c_head_p;
+    i2c_next_p = result_p->i2c_head_p;
+    while (i2c_curr_p){
+        i2c_next_p = i2c_curr_p->next;
+        kfree(i2c_curr_p->i2c_client_p);
+        kfree(i2c_curr_p);
+        i2c_curr_p = i2c_next_p;
+    }
+err_create_ioexp_setup_attr_fail:
+    kfree(result_p);
+err_create_ioexp_fail:
+    SWPS_ERR("%s: fail! <id>:%d <type>:%d \n",
+             __func__, ioexp_id, ioexp_type);
+    return NULL;
+}
+
+
+int
+create_ioexp_obj(int ioexp_id,
+                 int ioexp_type,
+                 struct ioexp_addr_s *addr_map_p,
+                 int run_mode){
+
+    struct ioexp_obj_s *ioexp_p  = NULL;
+
+    ioexp_p = _create_ioexp_obj(ioexp_id, ioexp_type,
+                                addr_map_p, run_mode);
+    if (!ioexp_p){
+        return -1;
+    }
+    if (ioexp_head_p == NULL){
+        ioexp_head_p = ioexp_p;
+        ioexp_tail_p = ioexp_p;
+        return 0;
+    }
+    ioexp_tail_p->next = ioexp_p;
+    ioexp_tail_p = ioexp_p;
+    return 0;
+}
+
+
+static int
+_init_ioexp_obj(struct ioexp_obj_s* self) {
+
+    char *err_msg   = "ERR";
+    char *func_name = "_init_ioexp_obj";
+
+    /* Setup IOEXP configure byte */
+    if (setup_ioexp_config(self) < 0){
+        err_msg = "setup_ioexp_config fail";
+        goto err_init_ioexp_obj;
+    }
+    /* Setup default data */
+    if (_ioexp_init_handler(self) < 0){
+        err_msg = "_ioexp_init_handler fail";
+        goto err_init_ioexp_obj;
+    }
+    /* Update all */
+    if (self->state == STATE_IOEXP_NORMAL){
+        if (self->update_all(self, 1, func_name) < 0){
+            err_msg = "update_all() fail";
+            goto err_init_ioexp_obj;
+        }
+    }
+    return 0;
+
+err_init_ioexp_obj:
+    SWPS_DEBUG("%s: %s\n", __func__, err_msg);
+    return -1;
+}
+
+
+int
+init_ioexp_objs(void){
+    /* Return value:
+     *   0: Success
+     *  -1: Detect topology error
+     *  -2: SWPS internal error
+     */
+
+    struct ioexp_obj_s *curr_p  = ioexp_head_p;
+
+    if (!curr_p) {
+        SWPS_ERR("%s: ioexp_head_p is NULL\n", __func__);
+        return -2;
+    }
+    while (curr_p) {
+        if (_init_ioexp_obj(curr_p) < 0) {
+            SWPS_DEBUG("%s: _init_ioexp_obj() fail\n", __func__);
+            return -1;
+        }
+        curr_p = curr_p->next;
+    }
+    SWPS_DEBUG("%s: done.\n", __func__);
+    return 0;
+}
+
+
+void
+clean_ioexp_objs(void){
+
+    struct ioexp_i2c_s *i2c_curr_p   = NULL;
+    struct ioexp_i2c_s *i2c_next_p   = NULL;
+    struct ioexp_obj_s *ioexp_next_p = NULL;
+    struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+    if (ioexp_head_p == NULL){
+        ioexp_tail_p = NULL;
+        return;
+    }
+    while(ioexp_curr_p){
+        ioexp_next_p = ioexp_curr_p->next;
+        if (ioexp_curr_p->ioexp_map_p) {
+            if (ioexp_curr_p->ioexp_map_p->map_addr) {
+                kfree(ioexp_curr_p->ioexp_map_p->map_addr);
+            }
+            kfree(ioexp_curr_p->ioexp_map_p);
+        }
+
+        i2c_curr_p = ioexp_curr_p->i2c_head_p;
+        while (i2c_curr_p) {
+            i2c_next_p = i2c_curr_p->next;
+            kfree(i2c_curr_p->i2c_client_p);
+            kfree(i2c_curr_p);
+            i2c_curr_p = i2c_next_p;
+        }
+        kfree(ioexp_curr_p);
+        ioexp_curr_p = ioexp_next_p;
+    }
+    ioexp_tail_p = NULL;
+    SWPS_DEBUG("%s: done.\n", __func__);
+}
+
+
+int
+check_ioexp_objs(void){
+
+    struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+    while (ioexp_curr_p){
+        if ( (ioexp_curr_p->check(ioexp_curr_p)) < 0){
+            SWPS_INFO("check IOEXP-%d fail! <type>:%d\n",
+                     ioexp_curr_p->ioexp_id, ioexp_curr_p->ioexp_type);
+            return -1;
+        }
+        ioexp_curr_p = ioexp_curr_p->next;
+    }
+    return 0;
+}
+
+
+struct ioexp_obj_s *
+get_ioexp_obj(int ioexp_id){
+
+    struct ioexp_obj_s *result_p = NULL;
+    struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+    while(ioexp_curr_p){
+        if (ioexp_curr_p->ioexp_id == ioexp_id){
+            result_p = ioexp_curr_p;
+            break;
+        }
+        ioexp_curr_p = ioexp_curr_p->next;
+    }
+    return result_p;
+}
+
+
+void
+unlock_ioexp_all(void) {
+
+    struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+    while(ioexp_curr_p){
+        mutex_unlock(&ioexp_curr_p->lock);
+        ioexp_curr_p = ioexp_curr_p->next;
+    }
+}
+
+
+int
+lock_ioexp_all(void) {
+
+    struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+
+    while(ioexp_curr_p){
+        mutex_lock(&ioexp_curr_p->lock);
+        ioexp_curr_p = ioexp_curr_p->next;
+    }
+    return 0;
+}
+
+
+int
+check_channel_tier_1(void) {
+
+    if ( (!_is_channel_ready(ioexp_head_p)) &&
+         (!_is_channel_ready(ioexp_tail_p)) ){
+        return -1;
+    }
+    return 0;
+}
+
+
+static int
+_scan_channel_tier_1(int force,
+                     int show_err) {
+
+    struct ioexp_obj_s *ioexp_curr_p = ioexp_head_p;
+    int ready = 0;
+
+    if (!ioexp_curr_p) {
+        goto err_scan_tier_1_channel;
+    }
+    while(ioexp_curr_p) {
+        ready = _is_channel_ready(ioexp_curr_p);
+        if ((!ready) && (!force)) {
+            goto err_scan_tier_1_channel;
+        }
+        ioexp_curr_p = ioexp_curr_p->next;
+    }
+    return 0;
+
+err_scan_tier_1_channel:
+    if (show_err) {
+        if (ioexp_curr_p) {
+            SWPS_INFO("%s: IOEXP-%d fail\n", __func__, ioexp_curr_p->ioexp_id);
+        } else {
+            SWPS_INFO("%s: IOEXP is null.\n", __func__);
+        }
+    }
+    return -1;
+}
+
+
+static int
+_scan_channel_tier_1_single(void) {
+
+    int ret       = 0;
+    int chan_id   = 0;
+    int fake_cid  = 0;
+    int fake_offs = 0;
+    int fake_addr = 0;
+    struct i2c_adapter *adap   = NULL;
+    struct i2c_client  *client = NULL;
+
+    if (ioexp_head_p->ioexp_id != ioexp_tail_p->ioexp_id) {
+        return 0;
+    }
+    /* Setup i2c_client */
+    chan_id   = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chan_id;
+    fake_addr = ioexp_head_p->ioexp_map_p->map_addr[fake_cid].chip_addr;
+    adap = i2c_get_adapter((chan_id + 1));
+    if(!adap){
+        SWPS_INFO("%s: Can not get adap!\n", __func__);
+        return 0;
+    }
+    client = kzalloc(sizeof(*client), GFP_KERNEL);
+    if (!client){
+        SWPS_INFO("%s: Can not kzalloc client!\n", __func__);
+        return 0;
+    }
+    client->adapter = adap;
+    client->addr = fake_addr;
+    /* Fouce move ioexp ptr to next */
+    ret = i2c_smbus_read_byte_data(client, fake_offs);
+    SWPS_DEBUG("%s: move ioexp_ptr done. <ret>:%d\n", __func__, ret);
+    kfree(client);
+    return 1;
+}
+
+
+int
+resync_channel_tier_1(void) {
+
+    char *emsg = "ERR";
+
+    if (!ioexp_head_p) {
+        emsg = "ioexp_head_p is NULL";
+        goto err_resync_ioexp_status_1;
+    }
+    /* Run all */
+    if (ioexp_head_p->ioexp_id == ioexp_tail_p->ioexp_id) {
+        _scan_channel_tier_1_single();
+    } else {
+        _scan_channel_tier_1(1, 0);
+    }
+    /* Check all */
+    if (_scan_channel_tier_1(0, 1) < 0) {
+        emsg = "resync tier-1 channel fail";
+        goto err_resync_ioexp_status_1;
+    }
+    return 0;
+
+err_resync_ioexp_status_1:
+    SWPS_ERR("%s: %s\n", __func__, emsg);
+    return -1;
+}
+
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h
new file mode 100644
index 000000000000..1af909e2466a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h
@@ -0,0 +1,187 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef IO_EXPANDER_H
+#define IO_EXPANDER_H
+
+#include <linux/types.h>
+
+
+/* IOEXP type define (SFP series) */
+#define IOEXP_TYPE_MAGINOLIA_NAB      (10101)
+#define IOEXP_TYPE_MAGINOLIA_4AB      (10102)
+#define IOEXP_TYPE_CYPRESS_NABC       (10103)
+#define IOEXP_TYPE_MAPLE_NABC         (10104)
+
+/* IOEXP type define (QSFP series) */
+#define IOEXP_TYPE_MAGINOLIA_7AB      (10201)
+#define IOEXP_TYPE_REDWOOD_P01P08     (10202)
+#define IOEXP_TYPE_REDWOOD_P09P16     (10203)
+#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204)
+#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205)
+#define IOEXP_TYPE_SPRUCE_7AB         (10206)
+#define IOEXP_TYPE_CYPRESS_7ABC       (10207)
+#define IOEXP_TYPE_TAHOE_5A           (10208)
+#define IOEXP_TYPE_TAHOE_6ABC         (10209)
+#define IOEXP_TYPE_SEQUOIA_NABC       (10210)
+#define IOEXP_TYPE_LAVENDER_P65       (10211)
+#define IOEXP_TYPE_MAPLE_0ABC         (10212)
+
+/* CPLD type define */
+#define CPLD_TYPE_COTTONWOOD          (10301)
+
+/* IOEXP mode define */
+#define IOEXP_MODE_POLLING            (19000)
+#define IOEXP_MODE_DIRECT             (19001)
+
+/* IOEXP state define */
+#define STATE_IOEXP_NORMAL                (0)
+#define STATE_IOEXP_INIT                 (-1)
+#define STATE_IOEXP_ABNORMAL             (-2)
+
+/* IOEXP error code define */
+#define ERR_IOEXP_NOTSUPPORT           (-100)
+#define ERR_IOEXP_UNINIT               (-101)
+#define ERR_IOEXP_BADCONF              (-102)
+#define ERR_IOEXP_ABNORMAL             (-103)
+#define ERR_IOEXP_NOSTATE              (-104)
+#define ERR_IOEXP_BADINPUT             (-105)
+#define ERR_IOEXP_UNEXCPT              (-199)
+
+#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args)
+#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args)
+#define SWPS_ERR(fmt, args...)  printk( KERN_ERR  "[SWPS] " fmt, ##args)
+
+#ifdef DEBUG_SWPS
+#    define SWPS_DEBUG(fmt, args...)  printk( KERN_DEBUG  "[SWPS] " fmt, ##args)
+#else
+#    define SWPS_DEBUG(fmt, args...)
+#endif
+
+
+struct ioexp_addr_s {
+    int chan_id;
+    int chip_addr;
+    int read_offset[8];
+    int write_offset[8];
+    int conf_offset[8];
+    uint8_t data_default[8]; 
+    uint8_t conf_default[8]; 
+};
+
+struct ioexp_i2c_s {
+    int chip_id;
+    struct i2c_client  *i2c_client_p;
+    struct ioexp_i2c_s *next;
+};
+
+
+struct ioexp_bitmap_s {
+    int chip_id;        /* IOEXP chip id        */
+    int ioexp_voffset;  /* IOEXP virtual offset */
+    int bit_shift;
+};
+
+struct ioexp_map_s {
+    int chip_amount;    /* Number of chips that IOEXP object content    */
+    int data_width;     /* Number of (Read/Write/Config) bytes          */
+    struct ioexp_addr_s   *map_addr;           /* Chip address info      */
+    struct ioexp_bitmap_s  map_present[10];    /* IOEXP for SFP / QSFP   */
+    struct ioexp_bitmap_s  map_tx_disable[10]; /* IOEXP for SFP          */
+    struct ioexp_bitmap_s  map_tx_fault[10];   /* IOEXP for SFP          */
+    struct ioexp_bitmap_s  map_rxlos[10];      /* IOEXP for SFP          */
+    struct ioexp_bitmap_s  map_reset[10];      /* IOEXP for QSFP         */
+    struct ioexp_bitmap_s  map_lpmod[10];      /* IOEXP for QSFP         */
+    struct ioexp_bitmap_s  map_modsel[10];     /* IOEXP for QSFP         */
+    struct ioexp_bitmap_s  map_hard_rs0[10];   /* IOEXP for QSFP         */
+    struct ioexp_bitmap_s  map_hard_rs1[10];   /* IOEXP for QSFP         */
+};
+
+struct ioexp_data_s {
+    uint8_t data[8];
+};
+
+struct ioexp_obj_s {
+
+    /* ============================
+     *  Object public property
+     * ============================
+     */
+    int ioexp_id;
+    int ioexp_type;
+
+    /* ============================
+     *  Object private property
+     * ============================
+     */
+    struct ioexp_data_s chip_data[16];   /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */
+    struct ioexp_map_s *ioexp_map_p;
+    struct ioexp_obj_s *next;
+    struct ioexp_i2c_s *i2c_head_p;
+    struct mutex lock;
+    int mode;
+    int state;
+
+    /* ===========================================
+     *  Object public functions
+     * ===========================================
+     */
+    int (*get_present)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_reset)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset);
+    int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset);
+    int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+    int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+    int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+    int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+    int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+    int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val);
+
+    /* ===========================================
+     *  Object private functions
+     * ===========================================
+     */
+    int (*init)(struct ioexp_obj_s *self);
+    int (*check)(struct ioexp_obj_s *self);
+    int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name);
+    int (*fsm_4_direct)(struct ioexp_obj_s* self);
+    int (*fsm_4_polling)(struct ioexp_obj_s* self);
+};
+
+
+struct ioexp_obj_s* get_ioexp_obj(int ioexp_id);
+int  create_ioexp_obj(int ioexp_id,
+                      int ioexp_type,
+                      struct ioexp_addr_s *addr_map_p,
+                      int run_mode);
+int  init_ioexp_objs(void);
+int  check_ioexp_objs(void);
+void clean_ioexp_objs(void);
+
+void unlock_ioexp_all(void);
+int  lock_ioexp_all(void);
+
+int  check_channel_tier_1(void);
+int  resync_channel_tier_1(void);
+
+/* Macro for bit control */
+#define SWP_BIT_SET(byte_val,bit_shift)   ((byte_val) |= (1<<(bit_shift)))
+#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift)))
+
+
+#endif /* IO_EXPANDER_H */
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c
new file mode 100644
index 000000000000..6fe8f599fb48
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c
@@ -0,0 +1,8389 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/kobject.h>
+#include <linux/delay.h>
+#include "io_expander.h"
+#include "transceiver.h"
+
+
+/* ========== Register EEPROM address mapping ==========
+ */
+struct eeprom_map_s eeprom_map_sfp = {
+    .addr_br           =0x50,  .page_br           =-1,  .offset_br           =12,   .length_br           =1,
+    .addr_cdr          =-1,    .page_cdr          =-1,  .offset_cdr          =-1,   .length_cdr          =-1,
+    .addr_comp_rev     =0x50,  .page_comp_rev     =-1,  .offset_comp_rev     =94,   .length_comp_rev     =1,
+    .addr_connector    =0x50,  .page_connector    =-1,  .offset_connector    =2,    .length_connector    =1,
+    .addr_diag_type    =0x50,  .page_diag_type    =-1,  .offset_diag_type    =92 ,  .length_diag_type    =1,
+    .addr_extbr        =-1,    .page_extbr        =-1,  .offset_extbr        =-1,   .length_extbr        =-1,
+    .addr_ext_id       =0x50,  .page_ext_id       =-1,  .offset_ext_id       =1,    .length_ext_id       =1,
+    .addr_id           =0x50,  .page_id           =-1,  .offset_id           =0,    .length_id           =1,
+    .addr_len_sm       =0x50,  .page_len_sm       =-1,  .offset_len_sm       =15,   .length_len_sm       =1,
+    .addr_len_smf      =0x50,  .page_len_smf      =-1,  .offset_len_smf      =14,   .length_len_smf      =1,
+    .addr_len_om1      =0x50,  .page_len_om1      =-1,  .offset_len_om1      =17,   .length_len_om1      =1,
+    .addr_len_om2      =0x50,  .page_len_om2      =-1,  .offset_len_om2      =16,   .length_len_om2      =1,
+    .addr_len_om3      =0x50,  .page_len_om3      =-1,  .offset_len_om3      =19,   .length_len_om3      =1,
+    .addr_len_om4      =0x50,  .page_len_om4      =-1,  .offset_len_om4      =18,   .length_len_om4      =1,
+    .addr_option       =0x50,  .page_option       =-1,  .offset_option       =64,   .length_option       =2,
+    .addr_rate_id      =0x50,  .page_rate_id      =-1,  .offset_rate_id      =13,   .length_rate_id      =1,
+    .addr_rx_am        =-1,    .page_rx_am        =-1,  .offset_rx_am        =-1,   .length_rx_am        =-1,
+    .addr_rx_em        =0x51,  .page_rx_em        =-1,  .offset_rx_em        =115,  .length_rx_em        =1,
+    .addr_rx_los       =-1,    .page_rx_los       =-1,  .offset_rx_los       =-1,   .length_rx_los       =-1,
+    .addr_rx_power     =0x51,  .page_rx_power     =-1,  .offset_rx_power     =104,  .length_rx_power     =2,
+    .addr_soft_rs0     =0x51,  .page_soft_rs0     =-1,  .offset_soft_rs0     =110,  .length_soft_rs0     =1,
+    .addr_soft_rs1     =0x51,  .page_soft_rs1     =-1,  .offset_soft_rs1     =118,  .length_soft_rs0     =1,
+    .addr_temp         =0x51,  .page_temp         =-1,  .offset_temp         =96,   .length_temp         =2,
+    .addr_trancomp     =0x50,  .page_trancomp     =-1,  .offset_trancomp     =3,    .length_trancomp     =8,
+    .addr_trancomp_ext =0x50,  .page_trancomp_ext =-1,  .offset_trancomp_ext =36,   .length_trancomp_ext =1,
+    .addr_tx_bias      =0x51,  .page_tx_bias      =-1,  .offset_tx_bias      =100,  .length_tx_bias      =2,
+    .addr_tx_disable   =-1,    .page_tx_disable   =-1,  .offset_tx_disable   =-1,   .length_tx_disable   =-1,
+    .addr_tx_eq        =0x51,  .page_tx_eq        =-1,  .offset_tx_eq        =114,  .length_tx_eq        =1,
+    .addr_tx_fault     =-1,    .page_tx_fault     =-1,  .offset_tx_fault     =-1,   .length_tx_fault     =-1,
+    .addr_tx_power     =0x51,  .page_tx_power     =-1,  .offset_tx_power     =102,  .length_tx_power     =2,
+    .addr_vendor_name  =0x50,  .page_vendor_name  =-1,  .offset_vendor_name  =20,   .length_vendor_name  =16,
+    .addr_vendor_pn    =0x50,  .page_vendor_pn    =-1,  .offset_vendor_pn    =40,   .length_vendor_pn    =16,
+    .addr_vendor_rev   =0x50,  .page_vendor_rev   =-1,  .offset_vendor_rev   =56,   .length_vendor_rev   =4,
+    .addr_vendor_sn    =0x50,  .page_vendor_sn    =-1,  .offset_vendor_sn    =68,   .length_vendor_sn    =16,
+    .addr_voltage      =0x51,  .page_voltage      =-1,  .offset_voltage      =98,   .length_voltage      =2,
+    .addr_wavelength   =0x50,  .page_wavelength   =-1,  .offset_wavelength   =60,   .length_wavelength   =2,
+};
+
+struct eeprom_map_s eeprom_map_qsfp = {
+    .addr_br           =0x50,  .page_br           =0,   .offset_br           =140,  .length_br           =1,
+    .addr_cdr          =-1,    .page_cdr          =-1,  .offset_cdr          =-1,   .length_cdr          =-1,
+    .addr_comp_rev     =0x50,  .page_comp_rev     =-1,  .offset_comp_rev     =1,    .length_comp_rev     =1,
+    .addr_connector    =0x50,  .page_connector    =0,   .offset_connector    =130,  .length_connector    =1,
+    .addr_diag_type    =0x50,  .page_diag_type    =0,   .offset_diag_type    =220,  .length_diag_type    =1,
+    .addr_extbr        =0x50,  .page_extbr        =0,   .offset_extbr        =222,  .length_extbr        =1,
+    .addr_ext_id       =0x50,  .page_ext_id       =0,   .offset_ext_id       =129,  .length_ext_id       =1,
+    .addr_id           =0x50,  .page_id           =0,   .offset_id           =128,  .length_id           =1,
+    .addr_len_sm       =-1,    .page_len_sm       =-1,  .offset_len_sm       =-1,   .length_len_sm       =-1,
+    .addr_len_smf      =0x50,  .page_len_smf      =0,   .offset_len_smf      =142,  .length_len_smf      =1,
+    .addr_len_om1      =0x50,  .page_len_om1      =0,   .offset_len_om1      =145,  .length_len_om1      =1,
+    .addr_len_om2      =0x50,  .page_len_om2      =0,   .offset_len_om2      =144,  .length_len_om2      =1,
+    .addr_len_om3      =0x50,  .page_len_om3      =0,   .offset_len_om3      =143,  .length_len_om3      =1,
+    .addr_len_om4      =0x50,  .page_len_om4      =0,   .offset_len_om4      =146,  .length_len_om4      =1,
+    .addr_option       =0x50,  .page_option       =0,   .offset_option       =193,  .length_option       =3,
+    .addr_rate_id      =-1,    .page_rate_id      =-1,  .offset_rate_id      =-1,   .length_rate_id      =-1,
+    .addr_rx_am        =-1,    .page_rx_am        =-1,  .offset_rx_am        =-1,   .length_rx_am        =-1,
+    .addr_rx_em        =-1,    .page_rx_em        =-1,  .offset_rx_em        =-1,   .length_rx_em        =-1,
+    .addr_rx_los       =0x50,  .page_rx_los       =-1,  .offset_rx_los       =3,    .length_rx_los       =1,
+    .addr_rx_power     =0x50,  .page_rx_power     =-1,  .offset_rx_power     =34,   .length_rx_power     =8,
+    .addr_soft_rs0     =-1,    .page_soft_rs0     =-1,  .offset_soft_rs0     =-1,   .length_soft_rs0     =-1,
+    .addr_soft_rs1     =-1,    .page_soft_rs1     =-1,  .offset_soft_rs1     =-1,   .length_soft_rs0     =-1,
+    .addr_temp         =0x50,  .page_temp         =-1,  .offset_temp         =22,   .length_temp         =2,
+    .addr_trancomp     =0x50,  .page_trancomp     =0,   .offset_trancomp     =131,  .length_trancomp     =8,
+    .addr_trancomp_ext =0x50,  .page_trancomp_ext =0,   .offset_trancomp_ext =192,  .length_trancomp_ext =1,
+    .addr_tx_bias      =0x50,  .page_tx_bias      =-1,  .offset_tx_bias      =42,   .length_tx_bias      =8,
+    .addr_tx_disable   =0x50,  .page_tx_disable   =-1,  .offset_tx_disable   =86,   .length_tx_disable   =1,
+    .addr_tx_eq        =-1,    .page_tx_eq        =-1,  .offset_tx_eq        =-1,   .length_tx_eq        =-1,
+    .addr_tx_fault     =0x50,  .page_tx_fault     =-1,  .offset_tx_fault     =4,    .length_tx_fault     =1,
+    .addr_tx_power     =0x50,  .page_tx_power     =-1,  .offset_tx_power     =50,   .length_tx_power     =8,
+    .addr_vendor_name  =0x50,  .page_vendor_name  =0,   .offset_vendor_name  =148,  .length_vendor_name  =16,
+    .addr_vendor_pn    =0x50,  .page_vendor_pn    =0,   .offset_vendor_pn    =168,  .length_vendor_pn    =16,
+    .addr_vendor_rev   =0x50,  .page_vendor_rev   =0,   .offset_vendor_rev   =184,  .length_vendor_rev   =2,
+    .addr_vendor_sn    =0x50,  .page_vendor_sn    =0,   .offset_vendor_sn    =196,  .length_vendor_sn    =16,
+    .addr_voltage      =0x50,  .page_voltage      =-1,  .offset_voltage      =26,   .length_voltage      =2,
+    .addr_wavelength   =0x50,  .page_wavelength   =0,   .offset_wavelength   =186,  .length_wavelength   =2,
+};
+
+struct eeprom_map_s eeprom_map_qsfp28 = {
+    .addr_br           =0x50,  .page_br           =0,   .offset_br           =140,  .length_br           =1,
+    .addr_cdr          =0x50,  .page_cdr          =-1,  .offset_cdr          =98,   .length_cdr          =1,
+    .addr_comp_rev     =0x50,  .page_comp_rev     =-1,  .offset_comp_rev     =1,    .length_comp_rev     =1,
+    .addr_connector    =0x50,  .page_connector    =0,   .offset_connector    =130,  .length_connector    =1,
+    .addr_diag_type    =0x50,  .page_diag_type    =0,   .offset_diag_type    =220,  .length_diag_type    =1,
+    .addr_extbr        =0x50,  .page_extbr        =0,   .offset_extbr        =222,  .length_extbr        =1,
+    .addr_ext_id       =0x50,  .page_ext_id       =0,   .offset_ext_id       =129,  .length_ext_id       =1,
+    .addr_id           =0x50,  .page_id           =0,   .offset_id           =128,  .length_id           =1,
+    .addr_len_sm       =-1,    .page_len_sm       =-1,  .offset_len_sm       =-1,   .length_len_sm       =-1,
+    .addr_len_smf      =0x50,  .page_len_smf      =0,   .offset_len_smf      =142,  .length_len_smf      =1,
+    .addr_len_om1      =0x50,  .page_len_om1      =0,   .offset_len_om1      =145,  .length_len_om1      =1,
+    .addr_len_om2      =0x50,  .page_len_om2      =0,   .offset_len_om2      =144,  .length_len_om2      =1,
+    .addr_len_om3      =0x50,  .page_len_om3      =0,   .offset_len_om3      =143,  .length_len_om3      =1,
+    .addr_len_om4      =0x50,  .page_len_om4      =0,   .offset_len_om4      =146,  .length_len_om4      =1,
+    .addr_option       =0x50,  .page_option       =0,   .offset_option       =193,  .length_option       =3,
+    .addr_rate_id      =-1,    .page_rate_id      =-1,  .offset_rate_id      =-1,   .length_rate_id      =-1,
+    .addr_rx_am        =0x50,  .page_rx_am        =3,   .offset_rx_am        =238,  .length_rx_am        =2,
+    .addr_rx_em        =0x50,  .page_rx_em        =3,   .offset_rx_em        =236,  .length_rx_em        =2,
+    .addr_rx_los       =0x50,  .page_rx_los       =-1,  .offset_rx_los       =3,    .length_rx_los       =1,
+    .addr_rx_power     =0x50,  .page_rx_power     =-1,  .offset_rx_power     =34,   .length_rx_power     =8,
+    .addr_soft_rs0     =-1,    .page_soft_rs0     =-1,  .offset_soft_rs0     =-1,   .length_soft_rs0     =-1,
+    .addr_soft_rs1     =-1,    .page_soft_rs1     =-1,  .offset_soft_rs1     =-1,   .length_soft_rs0     =-1,
+    .addr_temp         =0x50,  .page_temp         =-1,  .offset_temp         =22,   .length_temp         =2,
+    .addr_trancomp     =0x50,  .page_trancomp     =0,   .offset_trancomp     =131,  .length_trancomp     =8,
+    .addr_trancomp_ext =0x50,  .page_trancomp_ext =0,   .offset_trancomp_ext =192,  .length_trancomp_ext =1,
+    .addr_tx_bias      =0x50,  .page_tx_bias      =-1,  .offset_tx_bias      =42,   .length_tx_bias      =8,
+    .addr_tx_disable   =0x50,  .page_tx_disable   =-1,  .offset_tx_disable   =86,   .length_tx_disable   =1,
+    .addr_tx_eq        =0x50,  .page_tx_eq        =3,   .offset_tx_eq        =234,  .length_tx_eq        =2,
+    .addr_tx_fault     =0x50,  .page_tx_fault     =-1,  .offset_tx_fault     =4,    .length_tx_fault     =1,
+    .addr_tx_power     =0x50,  .page_tx_power     =-1,  .offset_tx_power     =50,   .length_tx_power     =8,
+    .addr_vendor_name  =0x50,  .page_vendor_name  =0,   .offset_vendor_name  =148,  .length_vendor_name  =16,
+    .addr_vendor_pn    =0x50,  .page_vendor_pn    =0,   .offset_vendor_pn    =168,  .length_vendor_pn    =16,
+    .addr_vendor_rev   =0x50,  .page_vendor_rev   =0,   .offset_vendor_rev   =184,  .length_vendor_rev   =2,
+    .addr_vendor_sn    =0x50,  .page_vendor_sn    =0,   .offset_vendor_sn    =196,  .length_vendor_sn    =16,
+    .addr_voltage      =0x50,  .page_voltage      =-1,  .offset_voltage      =26,   .length_voltage      =2,
+    .addr_wavelength   =0x50,  .page_wavelength   =0,   .offset_wavelength   =186,  .length_wavelength   =2,
+};
+
+
+/* ========== Utility Functions ==========
+ */
+static int
+get_bit(uint8_t origin_byte, int bit_shift) {
+    return (int)((origin_byte >> bit_shift) & 0x1);
+}
+
+static int
+transform_word_to_int(uint8_t hight_byte,
+                      uint8_t low_byte) {
+    return ((((int)hight_byte) << 8) + (int)low_byte);
+}
+
+void
+alarm_msg_2_user(struct transvr_obj_s *self,
+                 char *emsg) {
+
+    SWPS_ERR("%s on %s.\n", emsg, self->swp_name);
+}
+
+
+/* ========== Private functions ==========
+ */
+static int
+_reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+reload_transvr_obj(struct transvr_obj_s *self,int new_type);
+
+static int
+_is_transvr_support_ctle(struct transvr_obj_s *self);
+
+static int
+_transvr_init_handler(struct transvr_obj_s *self);
+
+int
+_transvr_clean_handler(struct transvr_obj_s *self);
+
+int
+_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self);
+
+
+void
+lock_transvr_obj(struct transvr_obj_s *self) {
+
+    mutex_lock(&self->lock);
+    self->curr_page = VAL_TRANSVR_PAGE_FREE;
+}
+
+
+void
+unlock_transvr_obj(struct transvr_obj_s *self) {
+
+    self->curr_page = VAL_TRANSVR_PAGE_FREE;
+    mutex_unlock(&self->lock);
+}
+
+
+static int
+_check_by_mode(struct transvr_obj_s *self,
+               int  (*attr_update_func)(struct transvr_obj_s *self, int show_err),
+               char *caller_name){
+
+    int return_val = ERR_TRANSVR_UNEXCPT;
+
+    switch (self->mode){
+        case TRANSVR_MODE_POLLING:
+            switch (self->state){
+                case STATE_TRANSVR_CONNECTED:
+                    goto ok_check_by_mode_1;
+                case STATE_TRANSVR_NEW:
+                case STATE_TRANSVR_INIT:
+                    return ERR_TRANSVR_UNINIT;
+                case STATE_TRANSVR_DISCONNECTED:
+                    return ERR_TRANSVR_UNPLUGGED;
+                case STATE_TRANSVR_UNEXCEPTED:
+                    return ERR_TRANSVR_ABNORMAL;
+                case STATE_TRANSVR_ISOLATED:
+                    return ERR_TRNASVR_BE_ISOLATED;
+                default:
+                    goto err_check_by_mode_1;
+            }
+            goto ok_check_by_mode_1;
+
+        case TRANSVR_MODE_DIRECT:
+            return_val = self->fsm_4_direct(self, caller_name);
+            if (return_val < 0){
+                return return_val;
+            }
+            goto ok_check_by_mode_1;
+
+        default:
+            goto err_check_by_mode_1;
+    }
+    goto ok_check_by_mode_1;
+
+ok_check_by_mode_1:
+    return attr_update_func(self, 0);
+
+err_check_by_mode_1:
+    SWPS_INFO("_check_by_mode: mode:%d state:%d\n", self->mode, self->state);
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+static void
+_transvr_clean_retry(struct transvr_obj_s *self) {
+    self->retry = 0;
+}
+
+
+static int
+_transvr_handle_retry(struct transvr_obj_s *self, int retry) {
+    /* Return: 0: keep retry
+     *        -1: stop retry
+     */
+    if (self->retry == 0) {
+        self->retry = retry;
+    }
+    self->retry -= 1;
+    if (self->retry <= 0) {
+        _transvr_clean_retry(self);
+        return -1;
+    }
+    return 0;
+}
+
+
+static int
+_common_setup_page(struct transvr_obj_s *self,
+                   int addr,
+                   int page,
+                   int offset,
+                   int len,
+                   int show_e) {
+    /* return:
+     *    0 : OK
+     *   -1 : EEPROM settings incorrect
+     *   -2 : I2C R/W failure
+     *   -3 : Undefined case
+     */
+    int retval = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    /* Check */
+    if ((addr < 0) || (offset < 0) || (len < 0)) {
+        emsg   = "EEPROM settings incorrect";
+        retval = -1;
+        goto err_common_setup_page;
+    }
+    /* Case1: continue access */
+    if ((self->i2c_client_p->addr == addr) &&
+        (self->curr_page == page)) {
+        return 0;
+    }
+    self->i2c_client_p->addr = addr;
+    /* Case2: select lower page */
+    if (page == -1) {
+        self->curr_page = page;
+        return 0;
+    }
+    /* Case3: select upper page */
+    if (page >= 0) {
+        goto upper_common_setup_page;
+    }
+    /* Unexpected case */
+    show_e = 1;
+    emsg   = "Unexpected case";
+    retval = -3;
+    goto err_common_setup_page;
+
+upper_common_setup_page:
+    if (i2c_smbus_write_byte_data(self->i2c_client_p,
+                                  VAL_TRANSVR_PAGE_SELECT_OFFSET,
+                                  page) < 0) {
+        emsg   = "I2C R/W failure";
+        retval = -2;
+        goto err_common_setup_page;
+    }
+    self->curr_page = page;
+    mdelay(VAL_TRANSVR_PAGE_SELECT_DELAY);
+    return 0;
+
+err_common_setup_page:
+    if (show_e) {
+        SWPS_INFO("%s: %s", __func__, emsg);
+        SWPS_INFO("%s: <addr>:0x%02x <page>:%d <offs>:%d <len>:%d\n",
+                __func__, addr, page, offset, len);
+    }
+    return retval;
+}
+
+/*
+static int
+_common_setup_password(struct transvr_obj_s *self,
+                       int addr,
+                       int page,
+                       int offs,
+                       uint8_t pwd[4],
+                       int show_e) {
+    int   i    = 0;
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    err = _common_setup_page(self, addr, page, offs, 4, show_e);
+    if (err < 0){
+        emsg = "setup EEPROM page fail";
+        goto err_common_setup_password;
+    }
+    for (i=0; i<4; i++) {
+        err = i2c_smbus_write_byte_data(self->i2c_client_p,
+                                        (offs + i),
+                                        pwd[i]);
+        if (err < 0){
+            emsg = "I2C R/W fail!";
+            goto err_common_setup_password;
+        }
+    }
+    return 0;
+
+err_common_setup_password:
+    if (show_e) {
+        SWPS_INFO("%s: %s <err>:%d\n", __func__, emsg,  err);
+    }
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+*/
+
+static int
+_common_update_uint8_attr(struct transvr_obj_s *self,
+                          int addr,
+                          int page,
+                          int offset,
+                          int len,
+                          uint8_t *buf,
+                          char *caller,
+                          int show_e){
+
+    int   i;
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    err = _common_setup_page(self, addr, page, offset, len, show_e);
+    if (err < 0){
+        emsg = "setup EEPROM page fail";
+        goto err_common_update_uint8_attr;
+    }
+    for (i=0; i<len; i++) {
+        err = i2c_smbus_read_byte_data(self->i2c_client_p, (offset + i));
+        if (err < 0){
+            emsg = "I2C R/W fail!";
+            goto err_common_update_uint8_attr;
+        }
+        buf[i] = err;
+    }
+    return 0;
+
+err_common_update_uint8_attr:
+    if (show_e) {
+        SWPS_INFO("%s: %s <caller>:%s <err>:%d\n",
+                  __func__, emsg, caller, err);
+    }
+    buf[0] = DEBUG_TRANSVR_HEX_VAL;
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_update_int_attr(struct transvr_obj_s *self,
+                        int addr,
+                        int page,
+                        int offset,
+                        int len,
+                        int *buf,
+                        char *caller,
+                        int show_e){
+
+    int   i;
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    err = _common_setup_page(self, addr, page, offset, len, show_e);
+    if (err < 0){
+        emsg = "setup EEPROM page fail";
+        goto err_common_update_int_attr;
+    }
+    for (i=0; i<len; i++) {
+        err = i2c_smbus_read_byte_data(self->i2c_client_p, (offset + i));
+        if (err < 0){
+            emsg = "I2C R/W fail!";
+            goto err_common_update_int_attr;
+        }
+        buf[i] = (int)err;
+    }
+    return 0;
+
+err_common_update_int_attr:
+    if (show_e) {
+        SWPS_INFO("%s: %s <caller>:%s <err>:%d\n",
+                  __func__, emsg, caller, err);
+    }
+    buf[0] = DEBUG_TRANSVR_INT_VAL;
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_update_string_attr(struct transvr_obj_s *self,
+                           int addr,
+                           int page,
+                           int offset,
+                           int len,
+                           char buf[],
+                           char *caller,
+                           int show_e){
+
+    int   i;
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    err = _common_setup_page(self, addr, page, offset, len, show_e);
+    if (err < 0){
+        emsg = "setup EEPROM page fail";
+        goto err_common_update_string_attr;
+    }
+    for (i=0; i<len; i++) {
+        err = i2c_smbus_read_byte_data(self->i2c_client_p, (offset + i));
+        if (err < 0){
+            emsg = "I2C R/W fail!";
+            goto err_common_update_string_attr;
+        }
+        buf[i] = (char)err;
+    }
+    return 0;
+
+err_common_update_string_attr:
+    if (show_e) {
+        SWPS_INFO("%s: %s <caller>:%s <err>:%d\n",
+                  __func__, emsg, caller, err);
+    }
+    buf[0] = 'e';
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_set_uint8_attr(struct transvr_obj_s *self,
+                       int addr,
+                       int page,
+                       int offset,
+                       uint8_t update,
+                       uint8_t *buf,
+                       char *caller,
+                       int show_e){
+    int   len  = 1;
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    if ((*buf) == update){
+        return 0;
+    }
+    err = _common_setup_page(self, addr, page, offset, len, show_e);
+    if (err < 0){
+        emsg = "setup EEPROM page fail";
+        goto err_common_set_uint8_attr_1;
+    }
+    err = i2c_smbus_write_byte_data(self->i2c_client_p,
+                                    offset,
+                                    update);
+    if (err < 0){
+        emsg = "I2C R/W fail!";
+        goto err_common_set_uint8_attr_1;
+    }
+    (*buf) = update;
+    return 0;
+
+err_common_set_uint8_attr_1:
+    if (show_e) {
+        SWPS_INFO("%s: %s <caller>:%s <err>:%d\n",
+                  __func__, emsg, caller, err);
+    }
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_set_uint8_array(struct transvr_obj_s *self,
+                       int addr,
+                       int page,
+                       int offs,
+                       int len,
+                       uint8_t update[],
+                       uint8_t buf[],
+                       char *caller,
+                       int show_e){
+    int   i    = 0;
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    err = _common_setup_page(self, addr, page, offs, len, show_e);
+    if (err < 0){
+        emsg = "setup EEPROM page fail";
+        goto err_common_set_uint8_attr_1;
+    }
+    for (i=0; i<len; i++) {
+        if (buf[i] == update[i]){
+            continue;
+        }
+        err = i2c_smbus_write_byte_data(self->i2c_client_p,
+                                        (offs + i),
+                                        update[i]);
+        if (err < 0){
+            emsg = "I2C R/W fail!";
+            goto err_common_set_uint8_attr_1;
+        }
+        buf[i] = update[i];
+    }
+    return 0;
+
+err_common_set_uint8_attr_1:
+    if (show_e) {
+        SWPS_INFO("%s: %s <caller>:%s <err>:%d <i>:%d\n",
+                  __func__, emsg, caller, err, i);
+    }
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+static int
+_common_update_attr_id(struct transvr_obj_s *self,
+                       int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_id,
+                                     self->eeprom_map_p->page_id,
+                                     self->eeprom_map_p->offset_id,
+                                     self->eeprom_map_p->length_id,
+                                     &(self->id),
+                                     "_common_update_attr_id",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_extended_id(struct transvr_obj_s *self,
+                                int show_err){
+    return  _common_update_uint8_attr(self,
+                                      self->eeprom_map_p->addr_ext_id,
+                                      self->eeprom_map_p->page_ext_id,
+                                      self->eeprom_map_p->offset_ext_id,
+                                      self->eeprom_map_p->length_ext_id,
+                                      &(self->ext_id),
+                                      "_common_update_attr_extended_id",
+                                      show_err);
+}
+
+
+static int
+_common_update_attr_connector(struct transvr_obj_s *self,
+                              int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_connector,
+                                     self->eeprom_map_p->page_connector,
+                                     self->eeprom_map_p->offset_connector,
+                                     self->eeprom_map_p->length_connector,
+                                     &(self->connector),
+                                     "_common_update_attr_connector",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_transvr_comp(struct transvr_obj_s *self,
+                                 int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_trancomp,
+                                     self->eeprom_map_p->page_trancomp,
+                                     self->eeprom_map_p->offset_trancomp,
+                                     self->eeprom_map_p->length_trancomp,
+                                     self->transvr_comp,
+                                     "_common_update_attr_transvr_comp",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_transvr_comp_ext(struct transvr_obj_s *self,
+                                     int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_trancomp_ext,
+                                     self->eeprom_map_p->page_trancomp_ext,
+                                     self->eeprom_map_p->offset_trancomp_ext,
+                                     self->eeprom_map_p->length_trancomp_ext,
+                                     &(self->transvr_comp_ext),
+                                     "_common_update_attr_transvr_comp_ext",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_vendor_name(struct transvr_obj_s *self,
+                                int show_err){
+    return _common_update_string_attr(self,
+                                      self->eeprom_map_p->addr_vendor_name,
+                                      self->eeprom_map_p->page_vendor_name,
+                                      self->eeprom_map_p->offset_vendor_name,
+                                      self->eeprom_map_p->length_vendor_name,
+                                      self->vendor_name,
+                                      "_common_update_attr_vendor_name",
+                                      show_err);
+}
+
+
+static int
+_common_update_attr_vendor_pn(struct transvr_obj_s *self,
+                              int show_err){
+    return _common_update_string_attr(self,
+                                      self->eeprom_map_p->addr_vendor_pn,
+                                      self->eeprom_map_p->page_vendor_pn,
+                                      self->eeprom_map_p->offset_vendor_pn,
+                                      self->eeprom_map_p->length_vendor_pn,
+                                      self->vendor_pn,
+                                      "_common_update_attr_vendor_pn",
+                                      show_err);
+}
+
+
+static int
+_common_update_attr_vendor_rev(struct transvr_obj_s *self,
+                               int show_err){
+    return _common_update_string_attr(self,
+                                      self->eeprom_map_p->addr_vendor_rev,
+                                      self->eeprom_map_p->page_vendor_rev,
+                                      self->eeprom_map_p->offset_vendor_rev,
+                                      self->eeprom_map_p->length_vendor_rev,
+                                      self->vendor_rev,
+                                      "_common_update_attr_vendor_rev",
+                                      show_err);
+}
+
+
+static int
+_common_update_attr_vendor_sn(struct transvr_obj_s *self,
+                              int show_err){
+    return _common_update_string_attr(self,
+                                      self->eeprom_map_p->addr_vendor_sn,
+                                      self->eeprom_map_p->page_vendor_sn,
+                                      self->eeprom_map_p->offset_vendor_sn,
+                                      self->eeprom_map_p->length_vendor_sn,
+                                      self->vendor_sn,
+                                      "_common_update_attr_vendor_sn",
+                                      show_err);
+}
+
+
+static int
+_common_update_attr_br(struct transvr_obj_s *self,
+                       int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_br,
+                                     self->eeprom_map_p->page_br,
+                                     self->eeprom_map_p->offset_br,
+                                     self->eeprom_map_p->length_br,
+                                     &(self->br),
+                                     "_common_update_attr_br",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_len_smf(struct transvr_obj_s *self,
+                            int show_err){
+    return _common_update_int_attr(self,
+                                   self->eeprom_map_p->addr_len_smf,
+                                   self->eeprom_map_p->page_len_smf,
+                                   self->eeprom_map_p->offset_len_smf,
+                                   self->eeprom_map_p->length_len_smf,
+                                   &(self->len_smf),
+                                   "_common_update_attr_len_smf",
+                                   show_err);
+}
+
+
+static int
+_common_update_attr_len_om1(struct transvr_obj_s *self,
+                            int show_err){
+    return _common_update_int_attr(self,
+                                   self->eeprom_map_p->addr_len_om1,
+                                   self->eeprom_map_p->page_len_om1,
+                                   self->eeprom_map_p->offset_len_om1,
+                                   self->eeprom_map_p->length_len_om1,
+                                   &(self->len_om1),
+                                   "_common_update_attr_len_om1",
+                                   show_err);
+}
+
+static int
+_common_update_attr_len_om2(struct transvr_obj_s *self,
+                            int show_err){
+    return _common_update_int_attr(self,
+                                   self->eeprom_map_p->addr_len_om2,
+                                   self->eeprom_map_p->page_len_om2,
+                                   self->eeprom_map_p->offset_len_om2,
+                                   self->eeprom_map_p->length_len_om2,
+                                   &(self->len_om2),
+                                   "_common_update_attr_len_om2",
+                                   show_err);
+}
+
+static int
+_common_update_attr_len_om3(struct transvr_obj_s *self,
+                            int show_err){
+    return _common_update_int_attr(self,
+                                   self->eeprom_map_p->addr_len_om3,
+                                   self->eeprom_map_p->page_len_om3,
+                                   self->eeprom_map_p->offset_len_om3,
+                                   self->eeprom_map_p->length_len_om3,
+                                   &(self->len_om3),
+                                   "_common_update_attr_len_om3",
+                                   show_err);
+}
+
+
+static int
+_common_update_attr_len_om4(struct transvr_obj_s *self,
+                            int show_err){
+    return _common_update_int_attr(self,
+                                   self->eeprom_map_p->addr_len_om4,
+                                   self->eeprom_map_p->page_len_om4,
+                                   self->eeprom_map_p->offset_len_om4,
+                                   self->eeprom_map_p->length_len_om4,
+                                   &(self->len_om4),
+                                   "_common_update_attr_len_om4",
+                                   show_err);
+}
+
+
+static int
+_common_update_attr_option(struct transvr_obj_s *self,
+                           int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_option,
+                                     self->eeprom_map_p->page_option,
+                                     self->eeprom_map_p->offset_option,
+                                     self->eeprom_map_p->length_option,
+                                     self->option,
+                                     "_common_update_attr_option",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_comp_rev(struct transvr_obj_s *self,
+                             int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_comp_rev,
+                                     self->eeprom_map_p->page_comp_rev,
+                                     self->eeprom_map_p->offset_comp_rev,
+                                     self->eeprom_map_p->length_comp_rev,
+                                     &(self->comp_rev),
+                                     "_common_update_attr_comp_rev",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_diag_type(struct transvr_obj_s *self,
+                              int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_diag_type,
+                                     self->eeprom_map_p->page_diag_type,
+                                     self->eeprom_map_p->offset_diag_type,
+                                     self->eeprom_map_p->length_diag_type,
+                                     &(self->diag_type),
+                                     "_common_update_attr_diag_type",
+                                     show_err);
+}
+
+
+static int
+_common_update_attr_wavelength(struct transvr_obj_s *self,
+                               int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_wavelength,
+                                     self->eeprom_map_p->page_wavelength,
+                                     self->eeprom_map_p->offset_wavelength,
+                                     self->eeprom_map_p->length_wavelength,
+                                     self->wavelength,
+                                     "_common_update_attr_wavelength",
+                                     show_err);
+}
+
+
+int
+_common_get_option_value(struct transvr_obj_s *self,
+                         int offset,
+                         int bit_shift) {
+    /* SFP:
+     *  - option[0] = A0h / 64
+     *  - option[1] = A0h / 65
+     * QSFP:
+     *  - option[0] = 00h / 193
+     *  - option[1] = 00h / 194
+     *  - option[2] = 00h / 195
+     */
+    return (self->option[offset] & (1 << bit_shift));
+}
+
+
+static int
+_sfp_update_attr_len_sm(struct transvr_obj_s *self,
+                        int show_err){
+    return _common_update_int_attr(self,
+                                   self->eeprom_map_p->addr_len_sm,
+                                   self->eeprom_map_p->page_len_sm,
+                                   self->eeprom_map_p->offset_len_sm,
+                                   self->eeprom_map_p->length_len_sm,
+                                   &(self->len_sm),
+                                   "_common_update_attr_len_sm",
+                                   show_err);
+}
+
+
+static int
+_sfp_update_attr_rate_id(struct transvr_obj_s *self,
+                         int show_err){
+    return _common_update_int_attr(self,
+                                   self->eeprom_map_p->addr_rate_id,
+                                   self->eeprom_map_p->page_rate_id,
+                                   self->eeprom_map_p->offset_rate_id,
+                                   self->eeprom_map_p->length_rate_id,
+                                   &(self->rate_id),
+                                   "_sfp_update_attr_rate_id",
+                                   show_err);
+}
+
+
+static int
+_sfp_update_attr_soft_rs0(struct transvr_obj_s *self,
+                          int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_soft_rs0,
+                                     self->eeprom_map_p->page_soft_rs0,
+                                     self->eeprom_map_p->offset_soft_rs0,
+                                     self->eeprom_map_p->length_soft_rs0,
+                                     &(self->soft_rs0),
+                                     "_sfp_update_attr_soft_rs0",
+                                     show_err);
+}
+
+
+static int
+_sfp_update_attr_soft_rs1(struct transvr_obj_s *self,
+                          int show_err){
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_soft_rs1,
+                                     self->eeprom_map_p->page_soft_rs1,
+                                     self->eeprom_map_p->offset_soft_rs1,
+                                     self->eeprom_map_p->length_soft_rs1,
+                                     &(self->soft_rs1),
+                                     "_sfp_update_attr_soft_rs1",
+                                     show_err);
+}
+
+
+int
+_sfp_is_diag_support(struct transvr_obj_s *self){
+
+    uint8_t bit_mask = 0xC0; /* 1100 0000 */
+    uint8_t en_val   = 0x40; /* 0100 0000 */
+    uint8_t checkval = (self->diag_type & bit_mask);
+
+    if (checkval == en_val) {
+        return 1;
+    }
+    return 0;
+}
+
+
+static int
+_sfp_update_attr_curr_temp(struct transvr_obj_s *self,
+                           int show_err){
+
+    if (!(_sfp_is_diag_support(self))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_temp,
+                                     self->eeprom_map_p->page_temp,
+                                     self->eeprom_map_p->offset_temp,
+                                     self->eeprom_map_p->length_temp,
+                                     self->curr_temp,
+                                     "_sfp_update_attr_curr_temp",
+                                     show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_voltage(struct transvr_obj_s *self,
+                              int show_err){
+
+    if (!(_sfp_is_diag_support(self))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_voltage,
+                                     self->eeprom_map_p->page_voltage,
+                                     self->eeprom_map_p->offset_voltage,
+                                     self->eeprom_map_p->length_voltage,
+                                     self->curr_voltage,
+                                     "_sfp_update_attr_curr_voltage",
+                                     show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_tx_bias(struct transvr_obj_s *self,
+                              int show_err){
+
+    if (!(_sfp_is_diag_support(self))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_bias,
+                                     self->eeprom_map_p->page_tx_bias,
+                                     self->eeprom_map_p->offset_tx_bias,
+                                     self->eeprom_map_p->length_tx_bias,
+                                     self->curr_tx_bias,
+                                     "_sfp_update_attr_curr_tx_bias",
+                                     show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_tx_power(struct transvr_obj_s *self,
+                               int show_err){
+
+    if (!(_sfp_is_diag_support(self))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_power,
+                                     self->eeprom_map_p->page_tx_power,
+                                     self->eeprom_map_p->offset_tx_power,
+                                     self->eeprom_map_p->length_tx_power,
+                                     self->curr_tx_power,
+                                     "_sfp_update_attr_curr_tx_power",
+                                     show_err);
+}
+
+
+static int
+_sfp_update_attr_curr_rx_power(struct transvr_obj_s *self,
+                               int show_err){
+
+    if (!(_sfp_is_diag_support(self))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_rx_power,
+                                     self->eeprom_map_p->page_rx_power,
+                                     self->eeprom_map_p->offset_rx_power,
+                                     self->eeprom_map_p->length_rx_power,
+                                     self->curr_rx_power,
+                                     "_sfp_update_attr_curr_rx_power",
+                                     show_err);
+}
+
+
+static int
+_sfp_update_attr_rx_em(struct transvr_obj_s *self,
+                       int show_err){
+
+    if (!_is_transvr_support_ctle(self)) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_rx_em,
+                                     self->eeprom_map_p->page_rx_em,
+                                     self->eeprom_map_p->offset_rx_em,
+                                     self->eeprom_map_p->length_rx_em,
+                                     self->rx_em,
+                                     "_sfp_update_attr_rx_em",
+                                     show_err);
+}
+
+
+static int
+_sfp_update_attr_tx_eq(struct transvr_obj_s *self,
+                       int show_err){
+
+    if (!_is_transvr_support_ctle(self)) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_eq,
+                                     self->eeprom_map_p->page_tx_eq,
+                                     self->eeprom_map_p->offset_tx_eq,
+                                     self->eeprom_map_p->length_tx_eq,
+                                     self->tx_eq,
+                                     "_sfp_update_attr_tx_eq",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_cdr(struct transvr_obj_s *self,
+                      int show_err){
+    if (self->type != TRANSVR_TYPE_QSFP_28){
+        self->cdr = DEBUG_TRANSVR_HEX_VAL;
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_cdr,
+                                     self->eeprom_map_p->page_cdr,
+                                     self->eeprom_map_p->offset_cdr,
+                                     self->eeprom_map_p->length_cdr,
+                                     &(self->cdr),
+                                     "_common_update_attr_cdr",
+                                     show_err);
+}
+
+
+static int
+_qsfg_update_attr_extbr(struct transvr_obj_s *self,
+                        int show_err) {
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_extbr,
+                                     self->eeprom_map_p->page_extbr,
+                                     self->eeprom_map_p->offset_extbr,
+                                     self->eeprom_map_p->length_extbr,
+                                     &(self->extbr),
+                                     "_common_update_attr_extbr",
+                                     show_err);
+}
+
+
+static int
+_qsfp_is_diag_support(struct transvr_obj_s *self,
+                      int diag_type) {
+    /* Input Parm: diag_type
+     * => 1 : temperature
+     * => 2 : voltage
+     * => 3 : tx relate
+     * => 4 : rx relate
+     */
+    uint8_t mask_b2 = 0x04; /* 0000 0100 */
+    uint8_t mask_b3 = 0x08; /* 0000 1000 */
+
+    switch (diag_type) {
+        case 1: /* temperature */
+        case 2: /* voltage */
+            /* Direct access target, because of spec not defined */
+            return 1;
+        case 3:
+        case 4:
+            /* [Note]
+             *   Due to lot of transceiver vendor defined it not rigorously and
+             *   consider of general support, we seem it as supported if there
+             *   are bit-2 OR bit-3 defined by transceiver vendor.
+             */
+            if ( ((self->diag_type & mask_b2) == mask_b2 ) ||
+                 ((self->diag_type & mask_b3) == mask_b3 ) ){
+                return 1;
+            }
+            return 0;
+        default:
+            SWPS_INFO("%s: undefined diag_type:%d\n",
+                      __func__, diag_type);
+            break;
+    }
+    return 0;
+}
+
+
+int
+_qsfp_is_implement_tx_disable(struct transvr_obj_s *self) {
+    /*
+     * 00h / Byte-195 / Bit-4
+     */
+    int byte = 2;
+    int bit  = 4;
+    return _common_get_option_value(self, byte, bit);
+}
+
+
+int
+_qsfp_is_implement_tx_fault(struct transvr_obj_s *self) {
+    /*
+     * 00h / Byte-195 / Bit-3
+     */
+    int byte = 2;
+    int bit  = 3;
+    return _common_get_option_value(self, byte, bit);
+}
+
+
+static int
+_qsfp_update_attr_curr_temp(struct transvr_obj_s *self,
+                            int show_err){
+    int diag_type = 1;
+
+    if (!(_qsfp_is_diag_support(self, diag_type))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_temp,
+                                     self->eeprom_map_p->page_temp,
+                                     self->eeprom_map_p->offset_temp,
+                                     self->eeprom_map_p->length_temp,
+                                     self->curr_temp,
+                                     "_qsfp_update_attr_curr_temp",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_voltage(struct transvr_obj_s *self,
+                               int show_err){
+    int diag_type = 2;
+
+    if (!(_qsfp_is_diag_support(self, diag_type))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_voltage,
+                                     self->eeprom_map_p->page_voltage,
+                                     self->eeprom_map_p->offset_voltage,
+                                     self->eeprom_map_p->length_voltage,
+                                     self->curr_voltage,
+                                     "_qsfp_update_attr_curr_voltage",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_tx_bias(struct transvr_obj_s *self,
+                               int show_err){
+    int diag_type = 3;
+
+    if (!(_qsfp_is_diag_support(self, diag_type))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_bias,
+                                     self->eeprom_map_p->page_tx_bias,
+                                     self->eeprom_map_p->offset_tx_bias,
+                                     self->eeprom_map_p->length_tx_bias,
+                                     self->curr_tx_bias,
+                                     "_qsfp_update_attr_curr_tx_bias",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_tx_power(struct transvr_obj_s *self,
+                                int show_err){
+    int diag_type = 3;
+
+    if (!(_qsfp_is_diag_support(self, diag_type))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_power,
+                                     self->eeprom_map_p->page_tx_power,
+                                     self->eeprom_map_p->offset_tx_power,
+                                     self->eeprom_map_p->length_tx_power,
+                                     self->curr_tx_power,
+                                     "_qsfp_update_attr_curr_tx_power",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_curr_rx_power(struct transvr_obj_s *self,
+                                int show_err){
+    int diag_type = 4;
+
+    if (!(_qsfp_is_diag_support(self, diag_type))) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_rx_power,
+                                     self->eeprom_map_p->page_rx_power,
+                                     self->eeprom_map_p->offset_rx_power,
+                                     self->eeprom_map_p->length_rx_power,
+                                     self->curr_rx_power,
+                                     "_qsfp_update_attr_curr_rx_power",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_soft_rx_los(struct transvr_obj_s *self,
+                              int show_err){
+
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_rx_los,
+                                     self->eeprom_map_p->page_rx_los,
+                                     self->eeprom_map_p->offset_rx_los,
+                                     self->eeprom_map_p->length_rx_los,
+                                     &(self->rx_los),
+                                     "_qsfp_update_attr_soft_rx_los",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_soft_tx_disable(struct transvr_obj_s *self,
+                                  int show_err){
+
+    if (!_qsfp_is_implement_tx_disable(self)) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_disable,
+                                     self->eeprom_map_p->page_tx_disable,
+                                     self->eeprom_map_p->offset_tx_disable,
+                                     self->eeprom_map_p->length_tx_disable,
+                                     &(self->tx_disable),
+                                     "_qsfp_update_attr_soft_tx_disable",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_soft_tx_fault(struct transvr_obj_s *self,
+                                int show_err){
+
+    if (!_qsfp_is_implement_tx_fault(self)) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_fault,
+                                     self->eeprom_map_p->page_tx_fault,
+                                     self->eeprom_map_p->offset_tx_fault,
+                                     self->eeprom_map_p->length_tx_fault,
+                                     &(self->tx_fault),
+                                     "_qsfp_update_attr_soft_tx_fault",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_tx_eq(struct transvr_obj_s *self,
+                        int show_err){
+
+    if (!_is_transvr_support_ctle(self)) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_eq,
+                                     self->eeprom_map_p->page_tx_eq,
+                                     self->eeprom_map_p->offset_tx_eq,
+                                     self->eeprom_map_p->length_tx_eq,
+                                     self->tx_eq,
+                                     "_qsfp_update_attr_tx_eq",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_rx_am(struct transvr_obj_s *self,
+                        int show_err){
+
+    if (!_is_transvr_support_ctle(self)) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_rx_am,
+                                     self->eeprom_map_p->page_rx_am,
+                                     self->eeprom_map_p->offset_rx_am,
+                                     self->eeprom_map_p->length_rx_am,
+                                     self->rx_am,
+                                     "_qsfp_update_attr_rx_am",
+                                     show_err);
+}
+
+
+static int
+_qsfp_update_attr_rx_em(struct transvr_obj_s *self,
+                        int show_err){
+
+    if (!_is_transvr_support_ctle(self)) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return _common_update_uint8_attr(self,
+                                     self->eeprom_map_p->addr_rx_em,
+                                     self->eeprom_map_p->page_rx_em,
+                                     self->eeprom_map_p->offset_rx_em,
+                                     self->eeprom_map_p->length_rx_em,
+                                     self->rx_em,
+                                     "_qsfp_update_attr_rx_em",
+                                     show_err);
+}
+
+
+int
+_common_update_attr_all(struct transvr_obj_s *self,
+                        int show_err){
+
+    char *err_str = "err";
+
+    if (_common_update_attr_id(self, show_err) < 0) {
+        err_str = "_common_update_attr_id";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_extended_id(self, show_err) < 0) {
+        err_str = "_common_update_attr_extended_id";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_connector(self, show_err) < 0) {
+        err_str = "_common_update_attr_connector";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_transvr_comp(self, show_err) < 0) {
+        err_str = "_common_update_attr_transvr_comp";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_transvr_comp_ext(self, show_err) < 0) {
+        err_str = "_common_update_attr_transvr_comp_ext";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_vendor_name(self, show_err) < 0) {
+        err_str = "_common_update_attr_vendor_name";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_vendor_pn(self, show_err) < 0) {
+        err_str = "_common_update_attr_vendor_pn";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_vendor_rev(self, show_err) < 0) {
+        err_str = "_common_update_attr_vendor_rev";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_vendor_sn(self, show_err) < 0) {
+        err_str = "_common_update_attr_vendor_sn";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_br(self, show_err) < 0) {
+        err_str = "_common_update_attr_br";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_len_smf(self, show_err) < 0) {
+        err_str = "_common_update_attr_len_smf";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_len_om1(self, show_err) < 0) {
+        err_str = "_common_update_attr_len_om1";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_len_om2(self, show_err) < 0) {
+        err_str = "_common_update_attr_len_om2";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_len_om3(self, show_err) < 0) {
+        err_str = "_common_update_attr_len_om3";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_len_om4(self, show_err) < 0) {
+        err_str = "_common_update_attr_len_om4";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_option(self, show_err) < 0) {
+        err_str = "_common_update_attr_option";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_comp_rev(self, show_err) < 0) {
+        err_str = "_common_update_attr_comp_rev";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_diag_type(self, show_err) < 0) {
+        err_str = "_common_update_attr_diag_type";
+        goto err_common_update_attr_all;
+    }
+    if (_common_update_attr_wavelength(self, show_err) < 0) {
+        err_str = "_common_update_attr_wavelength";
+        goto err_common_update_attr_all;
+    }
+    return 0;
+
+err_common_update_attr_all:
+    if (show_err){
+        SWPS_INFO("%s: fail at:%s <swp>:%s\n", __func__, err_str, self->swp_name);
+    }
+    return -1;
+}
+
+
+int
+_sfp_update_attr_all(struct transvr_obj_s *self,
+                     int show_err){
+
+    char *err_str  = DEBUG_TRANSVR_STR_VAL;
+
+    if (_common_update_attr_all(self, show_err) < 0){
+        err_str = "_common_update_attr_all";
+        goto err_sfp_update_attr_all;
+    }
+    if (_sfp_update_attr_len_sm(self, show_err) < 0) {
+        err_str = "_sfp_update_attr_len_sm";
+        goto err_sfp_update_attr_all;
+    }
+    if (_sfp_update_attr_rate_id(self, show_err) < 0) {
+        err_str = "_sfp_update_attr_rate_id";
+        goto err_sfp_update_attr_all;
+    }
+    if ((self->rate_id) > 0) {
+        if (_sfp_update_attr_soft_rs0(self, show_err) < 0) {
+            err_str = "_sfp_update_attr_soft_rs0";
+            goto err_sfp_update_attr_all;
+        }
+        if (_sfp_update_attr_soft_rs1(self, show_err) < 0) {
+            err_str = "_sfp_update_attr_soft_rs1";
+            goto err_sfp_update_attr_all;
+        }
+    }
+    return 0;
+
+err_sfp_update_attr_all:
+    if (show_err){
+        SWPS_INFO("%s: fail at:%s <swp>:%s\n", __func__, err_str, self->swp_name);
+    }
+    return -1;
+}
+
+
+int
+_qsfp_update_attr_all(struct transvr_obj_s *self,
+                      int show_err){
+
+    char *err_str  = DEBUG_TRANSVR_STR_VAL;
+
+    if (_common_update_attr_all(self, show_err) < 0){
+        err_str = "_common_update_attr_all";
+        goto err_qsfp_update_attr_all;
+    }
+    if (_qsfg_update_attr_extbr(self, show_err) < 0) {
+        err_str = "_qsfg_update_attr_extbr";
+        goto err_qsfp_update_attr_all;
+    }
+    if (self->type == TRANSVR_TYPE_QSFP_28) {
+        if (_qsfp_update_attr_cdr(self, 1) < 0) {
+            err_str = "_qsfp_update_attr_cdr";
+            goto err_qsfp_update_attr_all;
+        }
+    }
+    return 0;
+
+err_qsfp_update_attr_all:
+    if (show_err){
+        SWPS_INFO("%s: fail at:%s <swp>:%s\n", __func__, err_str, self->swp_name);
+    }
+    return -1;
+}
+
+
+/* ========== Object functions for common type ==========
+ */
+int
+_common_count_temp(uint8_t high_byte,
+                   uint8_t low_byte,
+                   char *buf_p) {
+    int sign = 0;
+    int high = 0;
+    int low  = 0;
+    int lmax = 8;
+
+    /* Count high */
+    sign = get_bit(high_byte,7);
+    SWP_BIT_CLEAR(high_byte, 7);
+    high = (int)high_byte;
+    if (sign == 1) {
+        high = 0 - high;
+    }
+    /* Count low */
+    low  = (get_bit(low_byte, 7) * 500);
+    low += (get_bit(low_byte, 6) * 250);
+    low += (get_bit(low_byte, 5) * 125);
+    low += (get_bit(low_byte, 4) *  62);
+    low  = (low / 100);
+    /* Integrate High and Low */
+    return snprintf(buf_p, lmax, "%d.%d\n", high, low);
+}
+
+
+int
+_common_count_voltage(uint8_t high_byte,
+                      uint8_t low_byte,
+                      char *buf_p) {
+    /* [Note]:
+     *   Internally measured transceiver supply voltage. Represented
+     *   as a 16 bit unsigned integer with the voltage defined as the
+     *   full 16 bit value (0-65535) with LSB equal to 100 uVolt,
+     *   yielding a total range of 0 to +6.55 Volts. Practical
+     *   considerations to be defined by transceiver manufacturer will
+     *   tend to limit the actual bounds of the supply voltage measurement.
+     *   Accuracy is vendor specific but must be better than 3% of the
+     *   manufacturer's nominal value over specified operating temperature
+     *   and voltage. Note that in some transceivers, transmitter supply
+     *   voltage and receiver supply voltage are isolated. In that case,
+     *   only one supply is monitored. Refer to the device specification
+     *   for more detail.
+     */
+    int total = 0;
+    int lmax  = 8;
+    int val_i = 0;
+    int val_f = 0;
+    /* unit: 100 uV (1mV=1000uV) */
+    total = transform_word_to_int(high_byte, low_byte);
+    val_i = ((total/10) / 1000);
+    val_f = ((total/10) - (val_i*1000));
+    /* Return Unit: 1 Volt */
+    return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f);
+}
+
+
+int
+_common_count_tx_bias(uint8_t high_byte,
+                      uint8_t low_byte,
+                      char *buf_p) {
+    /* [Note]
+     *   Measured TX bias current in uA. Represented as a 16 bit unsigned
+     *   integer with the current defined as the full 16 bit value (0-65535)
+     *   with LSB equal to 2 uA, yielding a total range of 0 to 131 mA.
+     *   Accuracy is vendor specific but must be better than 10% of the
+     *   manufacturer's nominal value over specified operating temperature
+     *   and voltage.
+     */
+    int total = 0;
+    int lmax  = 8;
+    int val_i = 0;
+    int val_f = 0;
+    /* unit: 2 uA (1mA=1000uA) */
+    total = transform_word_to_int(high_byte, low_byte);
+    val_i = ((total*2) / 1000);
+    val_f = (((total*2) - (val_i*1000)) / 100);
+    /* Return Unit: 1 mA */
+    return snprintf(buf_p, lmax, "%d.%01d\n", val_i, val_f);
+}
+
+
+int
+_common_count_tx_power(uint8_t high_byte,
+                       uint8_t low_byte,
+                       char *buf_p) {
+    /* [Note]
+     *   Measured TX output power in mW. Represented as a 16 bit unsigned
+     *   integer with the power defined as the full 16 bit value (0-65535)
+     *   with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW
+     *   (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of
+     *   laser monitor photodiode current. It is factory calibrated to absolute
+     *   units using the most representative fiber output type. Accuracy is
+     *   vendor specific but must be better than 3dB over specified temperature
+     *   and voltage. Data is not valid when the transmitter is disabled.
+     */
+    int total = 0;
+    int lmax  = 8;
+    int val_i = 0;
+    int val_f = 0;
+    /* unit: 0.1 uW (1mW=1000uW) */
+    total = transform_word_to_int(high_byte, low_byte);
+    val_i = ((total/10) / 1000);
+    val_f = ((total/10) - (val_i*1000));
+    /* Return Unit: 1 mW */
+    return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f);
+}
+
+
+int
+_common_count_rx_power(uint8_t high_byte,
+                       uint8_t low_byte,
+                       char *buf_p) {
+    /* [Note]
+     *   Measured RX received optical power in mW. Value can represent either
+     *   average received power or OMA depending upon how bit 3 of byte 92 (A0h)
+     *   is set. Represented as a 16 bit unsigned integer with the power defined
+     *   as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a
+     *   total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is
+     *   dependent upon the exact optical wavelength. For the vendor specified
+     *   wavelength, accuracy shall be better than 3dB over specified temperature
+     *   and voltage.
+     */
+    int total = 0;
+    int lmax  = 8;
+    int val_i = 0;
+    int val_f = 0;
+    /* unit: 0.1 uW (1mW=1000uW) */
+    total = transform_word_to_int(high_byte, low_byte);
+    val_i = ((total/10) / 1000);
+    val_f = ((total/10) - (val_i*1000));
+    /* Return Unit: 1 mW */
+    return snprintf(buf_p, lmax, "%d.%03d\n", val_i, val_f);
+}
+
+
+int
+_common_count_wavelength(struct transvr_obj_s *self,
+                         uint8_t high_byte,
+                         uint8_t low_byte) {
+    /* [Note]
+     *  SFP : uint 1 um.
+     *  QSFP: unit 0.05 um.
+     */
+    int total = 0;
+
+    total = transform_word_to_int(high_byte, low_byte);
+    switch (self->type) {
+        case TRANSVR_TYPE_SFP:
+            return total;
+
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+        case TRANSVR_TYPE_QSFP_28:
+            return (total/20);
+
+        default:
+            break;
+    }
+    return ERR_TRANSVR_UNDEFINED;
+}
+
+
+int
+common_get_id(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_id,
+                                  "common_get_id");
+    if (err_code < 0){
+        return err_code;
+    }
+    /* Transform to INT to show error case */
+    return (int)self->id;
+}
+
+
+int
+common_get_ext_id(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_extended_id,
+                                  "common_get_ext_id");
+    if (err_code < 0){
+        return err_code;
+    }
+    /* Transform to INT to show error case */
+    return (int)self->ext_id;
+}
+
+
+int
+common_get_connector(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_connector,
+                                  "common_get_connector");
+    if (err_code < 0){
+        return err_code;
+    }
+    /* Transform to INT to show error case */
+    return (int)self->connector;
+}
+
+
+int
+common_get_vendor_name(struct transvr_obj_s *self, char *buf){
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name);
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_vendor_name,
+                         "common_get_vendor_name");
+    memset(buf, 0, LEN_TRANSVR_M_STR);
+    if (err < 0){
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+    }
+    return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_name);
+}
+
+
+int
+common_get_vendor_pn(struct transvr_obj_s *self, char *buf) {
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn);
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_vendor_pn,
+                         "common_get_vendor_pn");
+    memset(buf, 0, LEN_TRANSVR_M_STR);
+    if (err < 0){
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+    }
+    return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_pn);
+}
+
+
+int
+common_get_vendor_rev(struct transvr_obj_s *self, char *buf) {
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev);
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_vendor_rev,
+                         "common_get_vendor_rev");
+    memset(buf, 0, LEN_TRANSVR_M_STR);
+    if (err < 0){
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+    }
+    return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_rev);
+}
+
+
+int
+common_get_vendor_sn(struct transvr_obj_s *self, char *buf) {
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn);
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_vendor_sn,
+                         "common_get_vendor_sn");
+    memset(buf, 0, LEN_TRANSVR_M_STR);
+    if (err < 0){
+        return snprintf(buf, LEN_TRANSVR_M_STR, "%d\n", err);
+    }
+    return snprintf(buf, LEN_TRANSVR_M_STR, "%s\n", self->vendor_sn);
+}
+
+
+int
+common_get_br(struct transvr_obj_s *self){
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return (int)self->br;
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_br,
+                         "common_get_br");
+    if (err < 0){
+        return err;
+    }
+    /* Transform to INT to show error case */
+    return (int)self->br;
+}
+
+
+int
+common_get_len_smf(struct transvr_obj_s *self){
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return self->len_smf;
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_len_smf,
+                         "common_get_len_smf");
+    if (err < 0){
+        return err;
+    }
+    return self->len_smf;
+}
+
+
+int
+common_get_len_om1(struct transvr_obj_s *self){
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return self->len_om1;
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_len_om1,
+                         "common_get_len_om1");
+    if (err < 0){
+        return err;
+    }
+    return self->len_om1;
+}
+
+
+int
+common_get_len_om2(struct transvr_obj_s *self){
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return self->len_om2;
+    }
+
+    err = _check_by_mode(self,
+                         &_common_update_attr_len_om2,
+                         "common_get_len_om2");
+    if (err < 0){
+        return err;
+    }
+    return self->len_om2;
+}
+
+
+int
+common_get_len_om3(struct transvr_obj_s *self){
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return self->len_om3;
+    }
+
+    err = _check_by_mode(self,
+                         &_common_update_attr_len_om3,
+                         "common_get_len_om3");
+    if (err < 0){
+        return err;
+    }
+    return self->len_om3;
+}
+
+
+int
+common_get_len_om4(struct transvr_obj_s *self){
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+
+    if (self->state == STATE_TRANSVR_CONNECTED &&
+        self->mode == TRANSVR_MODE_POLLING &&
+        TRANSVR_INFO_CACHE_ENABLE) {
+        return self->len_om4;
+    }
+    err = _check_by_mode(self,
+                         &_common_update_attr_len_om4,
+                         "common_get_len_om4");
+    if (err < 0){
+        return err;
+    }
+    return self->len_om4;
+}
+
+
+int
+common_get_comp_extended(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_transvr_comp_ext,
+                                  "common_get_comp_extended");
+    if (err_code < 0){
+        return err_code;
+    }
+    return self->transvr_comp_ext;
+}
+
+
+int
+common_get_comp_rev(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_comp_rev,
+                                  "common_get_comp_rev");
+    if (err_code < 0){
+        return err_code;
+    }
+    return self->comp_rev;
+}
+
+
+int
+common_get_info(struct transvr_obj_s *self){
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return self->state;
+    }
+    return self->info;
+}
+
+
+int
+_common_get_if_lane(struct transvr_obj_s *self,
+                    char *result){
+    int  i = 0;
+    int  tmp_val = 0;
+    char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL;
+
+    memset(result, 0, LEN_TRANSVR_M_STR);
+
+    for (i=0; i<ARRAY_SIZE(self->lane_id); i++) {
+        tmp_val = self->lane_id[i];
+        if (tmp_val < 1) {
+            break;
+        }
+        memset(tmp_str, 0, LEN_TRANSVR_M_STR);
+        if (i == 0) {
+            snprintf(tmp_str, LEN_TRANSVR_M_STR, "%d", tmp_val);
+        } else {
+            snprintf(tmp_str, LEN_TRANSVR_M_STR, ",%d", tmp_val);
+        }
+        strncat(result, tmp_str, LEN_TRANSVR_M_STR);
+    }
+    if (i == 0) {
+        return EVENT_TRANSVR_TASK_FAIL;
+    }
+    return 0;
+}
+
+
+int
+common_get_if_lane(struct transvr_obj_s *self,
+                   char *buf_p){
+
+    char tmp_str[LEN_TRANSVR_M_STR] = DEBUG_TRANSVR_STR_VAL;
+
+    if (self->ioexp_obj_p->state != STATE_IOEXP_NORMAL) {
+        return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n", ERR_TRANSVR_ABNORMAL);
+    }
+    if (_common_get_if_lane(self, tmp_str) < 0) {
+        return snprintf(buf_p, LEN_TRANSVR_M_STR, "%d\n" ,ERR_TRANSVR_ABNORMAL);
+    }
+    return snprintf(buf_p, LEN_TRANSVR_M_STR, "%s\n" ,tmp_str);
+}
+
+
+int
+sfp_get_len_sm(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_sfp_update_attr_len_sm,
+                                  "sfp_get_len_sm");
+    if (err_code < 0){
+        return err_code;
+    }
+    return self->len_sm;
+}
+
+
+int
+sfp_get_rate_id(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_sfp_update_attr_rate_id,
+                                  "sfp_get_rate_id");
+    if (err_code < 0){
+        return err_code;
+    }
+    return self->rate_id;
+}
+
+
+int
+sfp_get_soft_rs0(struct transvr_obj_s *self){
+    /* Note:
+     *   SFP Soft Rate_Select Select [aka. "RS(0)"] address
+     *   A2h, offset: 110, bit 3 (begin form 0)
+     */
+    int err_code    = DEBUG_TRANSVR_INT_VAL;
+    int bit_shift   = 3;
+    uint8_t result  = 0x00;
+    uint8_t bitmask = (1 << bit_shift);
+
+    /* Check rate identifier is supported */
+    err_code = self->get_rate_id(self);
+    if (err_code <= 0) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    /* Update and check */
+    err_code = _check_by_mode(self,
+                              &_sfp_update_attr_soft_rs0,
+                              "sfp_get_soft_rs0");
+    if (err_code <0){
+        return err_code;
+    }
+    result = (self->soft_rs0 & bitmask);
+    if (result == bitmask) {
+        return 1;
+    }
+    if (result == 0) {
+        return 0;
+    }
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+int
+sfp_get_soft_rs1(struct transvr_obj_s *self){
+    /* Note:
+     *   SFP Soft RS(1) Select address
+     *   A2h, offset: 118, bit 3 (begin form 0)
+     */
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+    int bit_shift = 3;
+    uint8_t result = 0x00;
+    uint8_t bitmask = (1 << bit_shift);
+
+    /* Check rate identifier is supported */
+    err_code = self->get_rate_id(self);
+    if (err_code <= 0) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    /* Update and check */
+    err_code = _check_by_mode(self,
+                              &_sfp_update_attr_soft_rs1,
+                              "sfp_get_soft_rs1");
+    if (err_code <0){
+        return err_code;
+    }
+    result = (self->soft_rs1 & bitmask);
+    if (result == bitmask) {
+        return 1;
+    }
+    if (result == 0) {
+        return 0;
+    }
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+int
+sfp_get_transvr_temp(struct transvr_obj_s *self,
+                     char *buf_p) {
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_sfp_update_attr_curr_temp,
+                              "sfp_get_transvr_temp");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    return _common_count_temp(self->curr_temp[0],
+                              self->curr_temp[1],
+                              buf_p);
+}
+
+
+int
+sfp_get_transvr_voltage(struct transvr_obj_s *self,
+                        char *buf_p) {
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_sfp_update_attr_curr_voltage,
+                              "sfp_get_transvr_voltage");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 Volt */
+    return _common_count_voltage(self->curr_voltage[0],
+                                 self->curr_voltage[1],
+                                 buf_p);
+}
+
+
+int
+sfp_get_transvr_tx_bias(struct transvr_obj_s *self,
+                        char *buf_p) {
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_sfp_update_attr_curr_tx_bias,
+                              "sfp_get_transvr_tx_bias");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 mA */
+    return _common_count_tx_bias(self->curr_tx_bias[0],
+                                 self->curr_tx_bias[1],
+                                 buf_p);
+}
+
+
+int
+sfp_get_transvr_tx_power(struct transvr_obj_s *self,
+                         char *buf_p) {
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_sfp_update_attr_curr_tx_power,
+                              "sfp_get_transvr_tx_power");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 mW */
+    return _common_count_tx_power(self->curr_tx_power[0],
+                                  self->curr_tx_power[1],
+                                  buf_p);
+}
+
+
+int
+sfp_get_transvr_rx_power(struct transvr_obj_s *self,
+                         char *buf_p) {
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_sfp_update_attr_curr_rx_power,
+                              "sfp_get_transvr_rx_power");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 mW */
+    return _common_count_rx_power(self->curr_rx_power[0],
+                                  self->curr_rx_power[0],
+                                  buf_p);
+}
+
+
+int
+sfp_get_transvr_rx_em(struct transvr_obj_s *self,
+                      char *buf_p) {
+
+    int limt = 8;
+    int err  = DEBUG_TRANSVR_INT_VAL;
+
+    err = _check_by_mode(self,
+                         &_sfp_update_attr_rx_em,
+                         "sfp_get_transvr_rx_em");
+    if (err < 0) {
+        return snprintf(buf_p, limt, "%d\n", err);
+    }
+    if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    return snprintf(buf_p, limt, "0x%02x\n", self->rx_em[0]);
+}
+
+
+int
+sfp_get_transvr_tx_eq(struct transvr_obj_s *self,
+                      char *buf_p) {
+
+    int limt = 8;
+    int err  = DEBUG_TRANSVR_INT_VAL;
+
+    err = _check_by_mode(self,
+                         &_sfp_update_attr_tx_eq,
+                         "sfp_get_transvr_tx_eq");
+    if (err < 0) {
+        return snprintf(buf_p, limt, "%d\n", err);
+    }
+    if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    return snprintf(buf_p, limt, "0x%02x\n", self->tx_eq[0]);
+}
+
+
+int
+_sfp_get_comp_extended(struct transvr_obj_s *self) {
+    /* Address: A0h / 36
+     * Reference: SFF-8024 TABLE 4-4
+     */
+    if ((self->state == STATE_TRANSVR_CONNECTED) ||
+        (self->state == STATE_TRANSVR_INIT) ) {
+        return (int)(self->transvr_comp_ext);
+    }
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+__sfp_get_comp_attr(struct transvr_obj_s *self,
+                     int array_offset) {
+    /* SFP Specification Compliance: A0h / 3-10
+     * transvr_comp[0-7] = 3 - 10
+     */
+    if ((self->state == STATE_TRANSVR_CONNECTED) ||
+        (self->state == STATE_TRANSVR_INIT) ) {
+        return (int)(self->transvr_comp[array_offset]);
+    }
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_sfp_get_comp_10g_eth_comp(struct transvr_obj_s *self) {
+    /* transvr_comp[0] = address A0h / 3
+     *
+     * 3 7: 10G Base-ER
+     * 3 6: 10GBASE-LRM
+     * 3 5: 10GBASE-LR
+     * 3 4: 10GBASE-SR
+     */
+    int bitmask = 0xf0; /* 11110000 */
+    return (__sfp_get_comp_attr(self, 0) & bitmask);
+}
+
+
+int
+_sfp_get_comp_1g_eth_comp(struct transvr_obj_s *self) {
+    /* transvr_comp[3] = address A0h / 6
+     *
+     * 6 7: BASE-PX *3
+     * 6 6: BASE-BX10 *3
+     * 6 5: 100BASE-FX
+     * 6 4: 100BASE-LX/LX10
+     * 6 3: 1000BASE-T
+     * 6 2: 1000BASE-CX
+     * 6 1: 1000BASE-LX *3
+     * 6 0: 1000BASE-SX
+     */
+    return __sfp_get_comp_attr(self, 3);
+}
+
+
+int
+_sfp_get_cable_tech(struct transvr_obj_s *self) {
+    /* transvr_comp[5] = address A0h / 8
+     *
+     * 8 3: Active Cable *8
+     * 8 2: Passive Cable *8
+     */
+    int bitmask = 0x0c; /* 00001100 */
+    return (__sfp_get_comp_attr(self, 5) & bitmask);
+}
+
+
+int
+sfp_get_comp_eth_1(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_transvr_comp,
+                                  "sfp_get_comp_eth_1");
+    if (err_code < 0){
+        return err_code;
+    }
+    return _sfp_get_comp_1g_eth_comp(self);
+}
+
+
+int
+sfp_get_comp_eth_10(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_transvr_comp,
+                                  "sfp_get_comp_eth_10");
+    if (err_code < 0){
+        return err_code;
+    }
+    return _sfp_get_comp_10g_eth_comp(self);
+}
+
+
+int
+_sfp_get_connector_type(struct transvr_obj_s *self) {
+    /* Address: A0h / 2
+     * Reference: SFF-8024 TABLE 4-3
+     */
+    if ((self->state == STATE_TRANSVR_CONNECTED) ||
+        (self->state == STATE_TRANSVR_INIT) ) {
+        return (int)(self->connector);
+    }
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+sfp_get_wavelength(struct transvr_obj_s *self,
+                   char *buf_p) {
+    /* [Note] Optical and Cable Variants Specification Compliance (SFF-8472)
+     * [Addr] A0h, Bytes 60-61
+     * [Note] For optical variants, as defined by having zero's in A0h Byte 8
+     *        bits 2 and 3, Bytes 60 and 61 denote nominal transmitter output
+     *        wavelength at room temperature. 16 bit value with byte 60 as high
+     *        order byte and byte 61 as low order byte. The laser wavelength is
+     *        equal to the 16 bit integer value in nm. This field allows the user
+     *        to read the laser wavelength directly, so it is not necessary to
+     *        infer it from the Transceiver Codes A0h Bytes 3 to 10 (see Table
+     *        5-3). This also allows specification of wavelengths not covered
+     *        in the Transceiver Codes, such as those used in coarse WDM systems.
+     *
+     *        For passive and active cable variants, a value of 00h for both A0h
+     *        Byte 60 and Byte 61 denotes laser wavelength or cable specification
+     *        compliance is unspecified.
+     */
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_common_update_attr_wavelength,
+                              "common_get_wavelength");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* unit: 1 um */
+    return snprintf(buf_p, lmax, "%d\n",
+            _common_count_wavelength(self,
+                                     self->wavelength[0],
+                                     self->wavelength[1]));
+}
+
+
+int
+sfp_get_1g_rj45_extphy_offset(struct transvr_obj_s *self, char *buf) {
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return ERR_TRANSVR_UNPLUGGED;
+    }
+    if ((self->info != TRANSVR_CLASS_BASE_T_1000) &&
+        (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    return snprintf(buf, LEN_TRANSVR_S_STR, "0x%02x\n", self->extphy_offset);
+}
+
+
+int
+sfp_get_1g_rj45_extphy_reg(struct transvr_obj_s *self, char *buf) {
+
+    int i      = 0;
+    int ret    = 0;
+    int retry  = 3;
+    int delay  = 200;
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return ERR_TRANSVR_UNPLUGGED;
+    }
+    if ((self->info != TRANSVR_CLASS_BASE_T_1000) &&
+        (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56,
+                           -1, self->extphy_offset, 1, 0) < 0) {
+        return -EIO;
+    }
+    for (i=0; i<retry; i++) {
+        ret = i2c_smbus_read_word_data(self->i2c_client_p, self->extphy_offset);
+        if (ret >=0) {
+            goto ok_sfp_get_1g_rj45_extphy_reg;
+        }
+        msleep(delay);
+    }
+    SWPS_INFO("%s: retry:%d fail <port>:%s <offset>:0x%02x\n",
+              __func__, retry, self->swp_name, self->extphy_offset);
+    return -EIO;
+
+ok_sfp_get_1g_rj45_extphy_reg:
+    ret = ((ret & 0x00ff) << 8) | ((ret & 0xff00) >> 8);
+    return snprintf(buf, LEN_TRANSVR_S_STR, "0x%04x\n", ret);
+}
+
+
+int
+__qsfp_get_power_cls(struct transvr_obj_s *self,
+                     int direct_access){
+
+    int err_code;
+    uint8_t detect_val;
+
+    /* Detect and Update power class attribute */
+    if (direct_access){
+        err_code = _check_by_mode(self,
+                                  &_common_update_attr_extended_id,
+                                  "__qsfp_get_power_cls");
+    } else {
+        err_code = self->ext_id;
+    }
+    if (err_code <0){
+        return err_code;
+    }
+    if (err_code == DEBUG_TRANSVR_HEX_VAL){
+        return ERR_TRANSVR_UPDATE_FAIL;
+    }
+    /* Clean data */
+    detect_val = self->ext_id;
+    SWP_BIT_CLEAR(detect_val, 2); /* Bit2: CDR RX present */
+    SWP_BIT_CLEAR(detect_val, 3); /* Bit3: CDR TX present */
+    SWP_BIT_CLEAR(detect_val, 4); /* Bit4: CLEI present   */
+    SWP_BIT_CLEAR(detect_val, 5); /* Bit5: reserved       */
+    /* Identify power class */
+    switch (detect_val) {
+        case 0:   /* Class_1: 00000000 */
+            return 1;
+        case 64:  /* Class_2: 01000000 */
+            return 2;
+        case 128: /* Class_3: 10000000 */
+            return 3;
+        case 192: /* Class_4: 11000000 */
+            return 4;
+        case 1:   /* Class_5: 00000001 */
+        case 193: /* Class_5: 11000001 */
+            return 5;
+        case 2:   /* Class_6: 00000010 */
+        case 194: /* Class_6: 11000010 */
+            return 6;
+        case 3:   /* Class_7: 00000011 */
+        case 195: /* Class_7: 11000011 */
+            return 7;
+        default:
+            break;
+    }
+    SWPS_INFO("%s: Detect undefined power class:%d\n", __func__, detect_val);
+    return ERR_TRANSVR_UNDEFINED;
+}
+
+
+int
+qsfp_get_power_cls(struct transvr_obj_s *self) {
+    return __qsfp_get_power_cls(self, 1);
+}
+
+
+int
+__qsfp_get_cdr_present(struct transvr_obj_s *self,
+                       int direct_access){
+
+    int retval;
+    int BIT_SHIFT = 2;
+    int BIT_MASK  = 0x3;
+
+    /* Detect and Update power class attribute */
+    if (direct_access) {
+        retval = _check_by_mode(self,
+                                &_common_update_attr_extended_id,
+                                "__qsfp_get_cdr_present");
+        if (retval < 0){
+            return retval;
+        }
+    }
+    retval = self->ext_id;
+    if (retval == DEBUG_TRANSVR_HEX_VAL){
+        return ERR_TRANSVR_UPDATE_FAIL;
+    }
+    /* Clean data and return */
+    return (int)(retval >> BIT_SHIFT & BIT_MASK);
+}
+
+
+int
+qsfp_get_cdr_present(struct transvr_obj_s *self) {
+    return __qsfp_get_cdr_present(self, 1);
+}
+
+
+int
+qsfp_get_cdr(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_qsfp_update_attr_cdr,
+                                  "qsfp_get_cdr");
+    if (err_code <0){
+        return err_code;
+    }
+
+    return self->cdr;
+}
+
+
+int
+__qsfp_get_comp_attr(struct transvr_obj_s *self,
+                     int array_offset) {
+    /* QSFP Specification Compliance: 00h / 131-138
+     * transvr_comp[0-7] = 131 - 138
+     */
+    if ((self->state == STATE_TRANSVR_CONNECTED) ||
+        (self->state == STATE_TRANSVR_INIT) ) {
+        return (int)(self->transvr_comp[array_offset]);
+    }
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_qsfp_get_comp_10_40_100_ethernet(struct transvr_obj_s *self) {
+    /* transvr_comp[0] = address 00h / 131
+     *
+     * 131 7: Extended: See section 6.3.23. The Extended Specification Compliance
+     *        Codes are maintained in the Transceiver Management section of SFF-
+     *        8024.
+     * 131 6: 10GBASE-LRM
+     * 131 5: 10GBASE-LR
+     * 131 4: 10GBASE-SR
+     * 131 3: 40GBASE-CR4
+     * 131 2: 40GBASE-SR4
+     * 131 1: 40GBASE-LR4
+     * 131 0: 40G Active Cable (XLPPI)
+     */
+    return __qsfp_get_comp_attr(self, 0);
+}
+
+
+int
+_qsfp_get_comp_sonet(struct transvr_obj_s *self) {
+    /* transvr_comp[1] = address 00h / 132
+     *
+     * 132 7-3: Reserved
+     * 132 2: OC 48, long reach
+     * 132 1: OC 48, intermediate reach
+     * 132 0: OC 48 short reach
+     */
+    return __qsfp_get_comp_attr(self, 1);
+}
+
+
+int
+_qsfp_get_comp_sas_sata(struct transvr_obj_s *self) {
+    /* transvr_comp[1] = address 00h / 132
+     *
+     * 133 7: SAS 24.0 Gb/s
+     * 133 6: SAS 12.0 Gb/s
+     * 133 5: SAS 6.0 Gb/s
+     * 133 4: SAS 3.0 Gb/s
+     * 133 3-0: Reserved
+     */
+    return __qsfp_get_comp_attr(self, 2);
+}
+
+
+int
+_qsfp_get_comp_ethernet(struct transvr_obj_s *self) {
+    /* transvr_comp[1] = address 00h / 132
+     *
+     * 134 7-4: Reserved
+     * 134 3: 1000BASE-T
+     * 134 2: 1000BASE-CX
+     * 134 1: 1000BASE-LX
+     * 134 0: 1000BASE-SX
+     */
+    return __qsfp_get_comp_attr(self, 3);
+}
+
+
+int
+_qsfp_get_comp_fc_link_length(struct transvr_obj_s *self) {
+    /* transvr_comp[1] = address 00h / 132
+     *
+     * 135 7: Very long distance (V)
+     * 135 6: Short distance (S)
+     * 135 5: Intermediate distance (I)
+     * 135 4: Long distance (L)
+     * 135 3: Medium (M)
+     */
+    int mask = 0xFC; /* 11111100 */
+    return (__qsfp_get_comp_attr(self, 4) & mask);
+}
+
+
+int
+_qsfp_get_comp_fc_trans_tech(struct transvr_obj_s *self) {
+    /* transvr_comp[1] = address 00h / 132
+     *
+     * 135 2: Reserved
+     * 135 1: Longwave laser (LC)
+     * 135 0: Electrical inter-enclosure (EL)
+     *
+     * 136 7: Electrical intra-enclosure
+     * 136 6: Shortwave laser w/o OFC (SN)
+     * 136 5: Shortwave laser w OFC (SL)
+     * 136 4: Longwave Laser (LL)
+     * 136 3-0: Reserved
+     *
+     * return value = [bit 8-15:addr 135][bit 0-7:addr 136]
+     */
+    int mask_135 = 7; /* 00000111 */
+    int val_135  = (__qsfp_get_comp_attr(self, 4) & mask_135);
+    int val_136  = __qsfp_get_comp_attr(self, 5);
+    return ((val_135 << 7) + val_136);
+}
+
+
+int
+_qsfp_get_comp_fc_trans_media(struct transvr_obj_s *self) {
+    /* transvr_comp[1] = address 00h / 132
+     *
+     * 137 7: Twin Axial Pair (TW)
+     * 137 6: Shielded Twisted Pair (TP)
+     * 137 5: Miniature Coax (MI)
+     * 137 4: Video Coax (TV)
+     * 137 3: Multi-mode 62.5 m (M6)
+     * 137 2: Multi-mode 50 m (M5)
+     * 137 1: Multi-mode 50 um (OM3)
+     * 137 0: Single Mode (SM)
+     */
+    return __qsfp_get_comp_attr(self, 6);
+}
+
+
+int
+_qsfp_get_comp_fc_speed(struct transvr_obj_s *self) {
+    /* transvr_comp[1] = address 00h / 132
+     *
+     * 138 7: 1200 MBps (per channel)
+     * 138 6: 800 MBps
+     * 138 5: 1600 MBps (per channel)
+     * 138 4: 400 MBps
+     * 138 3: 3200 MBps (per channel)
+     * 138 2: 200 MBps
+     * 138 1: Extended: See section 6.3.23. The Extended Specification
+     *        Compliance Codes are maintained in the Transceiver Management
+     *        section of SFF-8024.
+     * 138 0: 100 MBps
+     */
+    return __qsfp_get_comp_attr(self, 7);
+}
+
+
+int
+_qsfp_get_comp_extended(struct transvr_obj_s *self) {
+    /* Address: 00h / 192
+     * Reference: SFF-8024 TABLE 4-4
+     */
+    if ((self->state == STATE_TRANSVR_CONNECTED) ||
+        (self->state == STATE_TRANSVR_INIT) ) {
+        return (int)(self->transvr_comp_ext);
+    }
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+qsfp_get_comp_eth(struct transvr_obj_s *self){
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_transvr_comp,
+                                  "qsfp_get_comp_eth");
+    if (err_code < 0){
+        return err_code;
+    }
+    return _qsfp_get_comp_ethernet(self);
+}
+
+
+int
+qsfp_get_comp_10_40(struct transvr_obj_s *self) {
+
+    int err_code = _check_by_mode(self,
+                                  &_common_update_attr_transvr_comp,
+                                  "qsfp_get_comp_10_40");
+    if (err_code < 0){
+        return err_code;
+    }
+    return _qsfp_get_comp_10_40_100_ethernet(self);
+}
+
+
+int
+_qsfp_get_connector_type(struct transvr_obj_s *self) {
+    /* Address: 00h / 130
+     * Reference: SFF-8024 TABLE 4-3
+     */
+    if ((self->state == STATE_TRANSVR_CONNECTED) ||
+        (self->state == STATE_TRANSVR_INIT) ) {
+        return (int)(self->connector);
+    }
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+qsfp_get_transvr_temp(struct transvr_obj_s *self,
+                     char *buf_p) {
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_curr_temp,
+                              "qsfp_get_transvr_temp");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_temp[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    return _common_count_temp(self->curr_temp[0],
+                              self->curr_temp[1],
+                              buf_p);
+}
+
+
+int
+qsfp_get_transvr_voltage(struct transvr_obj_s *self,
+                         char *buf_p) {
+
+    int lmax = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_curr_voltage,
+                              "qsfp_get_transvr_voltage");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_voltage[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 Volt */
+    return _common_count_voltage(self->curr_voltage[0],
+                                 self->curr_voltage[1],
+                                 buf_p);
+}
+
+
+int
+qsfp_get_transvr_tx_eq(struct transvr_obj_s *self,
+                       char *buf_p) {
+
+    int limt = 8;
+    int err  = DEBUG_TRANSVR_INT_VAL;
+
+    err = _check_by_mode(self,
+                         &_qsfp_update_attr_tx_eq,
+                         "qsfp_get_transvr_tx_eq");
+    if (err < 0) {
+        return snprintf(buf_p, limt, "%d\n", err);
+    }
+    if ((self->tx_eq[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    return snprintf(buf_p, limt, "0x%02x%02x\n",
+                    self->tx_eq[0], self->tx_eq[1]);
+}
+
+
+int
+qsfp_get_transvr_rx_am(struct transvr_obj_s *self,
+                       char *buf_p) {
+
+    int limt = 8;
+    int err  = DEBUG_TRANSVR_INT_VAL;
+
+    err = _check_by_mode(self,
+                         &_qsfp_update_attr_rx_am,
+                         "qsfp_get_transvr_rx_am");
+    if (err < 0) {
+        return snprintf(buf_p, limt, "%d\n", err);
+    }
+    if ((self->rx_am[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    return snprintf(buf_p, limt, "0x%02x%02x\n",
+                    self->rx_am[0], self->rx_am[1]);
+}
+
+
+int
+qsfp_get_transvr_rx_em(struct transvr_obj_s *self,
+                       char *buf_p) {
+
+    int limt = 8;
+    int err  = DEBUG_TRANSVR_INT_VAL;
+
+    err = _check_by_mode(self,
+                         &_qsfp_update_attr_rx_em,
+                         "qsfp_get_transvr_rx_em");
+    if (err < 0) {
+        return snprintf(buf_p, limt, "%d\n", err);
+    }
+    if ((self->rx_em[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, limt, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    return snprintf(buf_p, limt, "0x%02x%02x\n",
+                    self->rx_em[0], self->rx_em[1]);
+}
+
+
+int
+_qsfp_get_channel_diag(uint8_t *data_array,
+                       int (*count_func)(uint8_t high_byte, uint8_t low_byte, char *buf_p),
+                       char *ch_name,
+                       char *result_p) {
+    int i, high, low;
+    int len_max = 128;
+    char ch_buf[4][16] = { DEBUG_TRANSVR_STR_VAL,
+                           DEBUG_TRANSVR_STR_VAL,
+                           DEBUG_TRANSVR_STR_VAL,
+                           DEBUG_TRANSVR_STR_VAL };
+
+    for (i=0; i<4; i++) {
+        high = (i*2);
+        low  = ((i*2) + 1);
+        count_func(data_array[high], data_array[low], ch_buf[i]);
+    }
+    return snprintf(result_p, len_max,
+                    "%s-%d:%s%s-%d:%s%s-%d:%s%s-%d:%s",
+                    ch_name, 1, ch_buf[0],
+                    ch_name, 2, ch_buf[1],
+                    ch_name, 3, ch_buf[2],
+                    ch_name, 4, ch_buf[3]);
+}
+
+
+int
+qsfp_get_soft_rx_los(struct transvr_obj_s *self,
+                     char *buf_p) {
+
+    int lmax      = 8;
+    int mask      = 0x0f; /* Bit 0 ~ Bit 3 */
+    int err_code  = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_soft_rx_los,
+                              "qsfp_get_soft_rx_los");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    return snprintf(buf_p, lmax, "0x%02x\n", (self->rx_los & mask));
+}
+
+
+int
+qsfp_get_soft_tx_disable(struct transvr_obj_s *self,
+                         char *buf_p) {
+
+    int lmax      = 8;
+    int mask      = 0x0f; /* Bit 0 ~ Bit 3 */
+    int err_code  = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_soft_tx_disable,
+                              "qsfp_get_soft_tx_disable");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_disable & mask));
+}
+
+
+int
+qsfp_get_soft_tx_fault(struct transvr_obj_s *self,
+                       char *buf_p) {
+
+    int lmax      = 8;
+    int mask      = 0x0f; /* Bit 0 ~ Bit 3 */
+    int err_code  = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_soft_tx_fault,
+                              "qsfp_get_soft_tx_fault");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    return snprintf(buf_p, lmax, "0x%02x\n", (self->tx_fault & mask));
+}
+
+
+int
+qsfp_get_auto_tx_disable(struct transvr_obj_s *self,
+                         char *buf_p) {
+
+    if (self->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) {
+        return snprintf(buf_p, LEN_TRANSVR_S_STR,
+                        "%d\n", ERR_TRANSVR_FUNC_DISABLE);
+    }
+    return snprintf(buf_p, LEN_TRANSVR_S_STR,
+                    "0x%02x\n", self->auto_tx_disable);
+}
+
+
+int
+qsfp_get_transvr_tx_bias(struct transvr_obj_s *self,
+                         char *buf_p) {
+
+    int lmax      = 8;
+    int err_code  = DEBUG_TRANSVR_INT_VAL;
+    char *ch_name = "TX";
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_curr_tx_bias,
+                              "qsfp_get_transvr_tx_bias");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_tx_bias[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 mA */
+    return _qsfp_get_channel_diag(self->curr_tx_bias,
+                                  _common_count_tx_bias,
+                                  ch_name,
+                                  buf_p);
+}
+
+
+int
+qsfp_get_transvr_tx_power(struct transvr_obj_s *self,
+                          char *buf_p) {
+
+    int lmax      = 8;
+    int err_code  = DEBUG_TRANSVR_INT_VAL;
+    char *ch_name = "TX";
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_curr_tx_power,
+                              "qsfp_get_transvr_tx_power");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 mW */
+    return _qsfp_get_channel_diag(self->curr_tx_power,
+                                  _common_count_tx_power,
+                                  ch_name,
+                                  buf_p);
+}
+
+
+int
+qsfp_get_transvr_rx_power(struct transvr_obj_s *self,
+                          char *buf_p) {
+
+    int lmax      = 8;
+    int err_code  = DEBUG_TRANSVR_INT_VAL;
+    char *ch_name = "RX";
+
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_curr_rx_power,
+                              "qsfp_get_transvr_rx_power");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->curr_tx_power[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* Return Unit: 1 mW */
+    return _qsfp_get_channel_diag(self->curr_rx_power,
+                                  _common_count_rx_power,
+                                  ch_name,
+                                  buf_p);
+}
+
+
+int
+qsfp_get_wavelength(struct transvr_obj_s *self,
+                    char *buf_p) {
+    /* [Desc] Wavelength or Copper Cable Attenuation (SFF-8636)
+     * [Addr] 00h 186-187
+     * [Note]
+     *  For optical free side devices, this parameter identifies the nominal
+     *  transmitter output wavelength at room temperature. This parameter is
+     *  a 16-bit hex value with Byte 186 as high order byte and Byte 187 as
+     *  low order byte. The laser wavelength is equal to the 16-bit integer value
+     *  divided by 20 in nm (units of 0.05 nm). This resolution should be adequate
+     *  to cover all relevant wavelengths yet provide enough resolution for all
+     *  expected DWDM applications. For accurate representation of controlled
+     *  wavelength applications, this value should represent the center of the
+     *  guaranteed wavelength range.
+     *  If the free side device is identified as copper cable these registers will
+     *  be used to define the cable attenuation. An indication of 0 dB attenuation
+     *  refers to the case where the attenuation is not known or is unavailable.
+     *  Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB.
+     *  Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB.
+     */
+    int lmax     = 8;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _check_by_mode(self,
+                              &_common_update_attr_wavelength,
+                              "common_get_wavelength");
+    if (err_code < 0) {
+        return snprintf(buf_p, lmax, "%d\n", err_code);
+    }
+    if ((self->wavelength[0]) == DEBUG_TRANSVR_HEX_VAL) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_UPDATE_FAIL);
+    }
+    /* unit: 1 um */
+    return snprintf(buf_p, lmax, "%d\n",
+            _common_count_wavelength(self,
+                                     self->wavelength[0],
+                                     self->wavelength[1]));
+}
+
+
+/*  Public Function for Setup Features
+ */
+static int
+__sfp_set_soft_rs(struct transvr_obj_s *self,
+                  int input_val,
+                  int address,
+                  int page,
+                  int offset,
+                  int bit_shift,
+                  uint8_t *attr_p,
+                  char *caller,
+                  int show_err) {
+
+    int   retval   = ERR_TRANSVR_UNEXCPT;
+    int   err_code = ERR_TRANSVR_UNEXCPT;
+    char *err_msg  = DEBUG_TRANSVR_STR_VAL;
+    uint8_t update_val = (*attr_p);
+
+    switch (input_val) {
+       case 0:
+           SWP_BIT_CLEAR(update_val, bit_shift);
+           break;
+       case 1:
+           SWP_BIT_SET(update_val, bit_shift);
+           break;
+       default:
+           retval   = ERR_TRANSVR_UNEXCPT;
+           err_code = ERR_TRANSVR_UNEXCPT;
+           err_msg  = "Exception occurs";
+           goto err_private_sfp_set_soft_rs_1;
+    }
+    err_code = _common_set_uint8_attr(self,
+                                      address,
+                                      page,
+                                      offset,
+                                      update_val,
+                                      attr_p,
+                                      caller,
+                                      show_err);
+    if (err_code < 0) {
+        retval   = err_code;
+        err_msg  = "Write data via i2c fail!";
+        goto err_private_sfp_set_soft_rs_1;
+    }
+    (*attr_p) = update_val;
+    return 0;
+
+err_private_sfp_set_soft_rs_1:
+    if (show_err) {
+        SWPS_INFO("%s: %s <ERR>:%d <Port>:%s\n <Input>:%d\n",
+                   __func__, err_msg, err_code, self->swp_name, input_val);
+    }
+    return retval;
+}
+
+
+static int
+_sfp_set_soft_rs(struct transvr_obj_s *self,
+                 int input_val,
+                 int address,
+                 int page,
+                 int offset,
+                 int bit_shift,
+                 int (*attr_update_func)(struct transvr_obj_s *self, int show_err),
+                 uint8_t *attr_p,
+                 char *caller,
+                 int show_err) {
+
+    int retval    = ERR_TRANSVR_UNEXCPT;
+    int err_code  = ERR_TRANSVR_UNEXCPT;
+    char *err_msg = DEBUG_TRANSVR_STR_VAL;
+
+    /* Check input value */
+    if ((input_val != 0) && (input_val != 1)){
+        retval   = ERR_TRANSVR_BADINPUT;
+        err_code = ERR_TRANSVR_BADINPUT;
+        err_msg  = "Input range incorrect!";
+        goto err_common_sfp_set_soft_rs_1;
+    }
+    /* Check rate identifier is supported */
+    err_code = self->get_rate_id(self);
+    if (err_code <= 0) {
+        switch (err_code) {
+            case 0:
+                retval  = ERR_TRANSVR_NOTSUPPORT;
+                err_msg = "Not support this feature";
+                break;
+            case ERR_TRANSVR_UNINIT:
+                retval  = ERR_TRANSVR_UNINIT;
+                err_msg = "Check CDR present fail!";
+                break;
+            case ERR_TRANSVR_UNPLUGGED:
+                retval  = ERR_TRANSVR_UNPLUGGED;
+                err_msg = "Transceiver unplugged!";
+                break;
+            default:
+                retval  = err_code;
+                err_msg = "Check Rate_ID fail!";
+                break;
+        }
+        goto err_common_sfp_set_soft_rs_1;
+    }
+    /* Check and update */
+    err_code = _check_by_mode(self,
+                              attr_update_func,
+                              caller);
+    if ( (err_code < 0) ||
+         ((*attr_p) == DEBUG_TRANSVR_HEX_VAL) ){
+        retval  = err_code;
+        err_msg = "Get current value fail!";
+        goto err_common_sfp_set_soft_rs_1;
+    }
+    /* Generate and update value */
+    return __sfp_set_soft_rs(self,
+                             input_val,
+                             address,
+                             page,
+                             offset,
+                             bit_shift,
+                             attr_p,
+                             caller,
+                             show_err);
+
+err_common_sfp_set_soft_rs_1:
+    if (show_err) {
+        SWPS_INFO("%s: %s <ERR>:%d <Port>:%s\n <Input>:%d\n",
+                  __func__, err_msg, err_code, self->swp_name, input_val);
+    }
+    return retval;
+}
+
+
+int
+sfp_set_soft_rs0(struct transvr_obj_s *self,
+                 int input_val) {
+    /* Note:
+     *   SFP Soft Rate_Select Select RX ["RS(0)"] address
+     *   A2h, offset: 110, bit 3
+     */
+    int bit_shift = 3;
+    int show_err  = 1;
+    return _sfp_set_soft_rs(self,
+                            input_val,
+                            self->eeprom_map_p->addr_soft_rs0,
+                            self->eeprom_map_p->page_soft_rs0,
+                            self->eeprom_map_p->offset_soft_rs0,
+                            bit_shift,
+                            &_sfp_update_attr_soft_rs0,
+                            &(self->soft_rs0),
+                            "sfp_set_soft_rs0",
+                            show_err);
+}
+
+
+int
+sfp_set_soft_rs1(struct transvr_obj_s *self,
+                 int input_val) {
+    /* Note:
+     *   SFP Soft Rate_Select Select RX ["RS(1)"] address
+     *   A2h, offset: 118, bit 3
+     */
+    int bit_shift = 3;
+    int show_err  = 1;
+    return _sfp_set_soft_rs(self,
+                            input_val,
+                            self->eeprom_map_p->addr_soft_rs1,
+                            self->eeprom_map_p->page_soft_rs1,
+                            self->eeprom_map_p->offset_soft_rs1,
+                            bit_shift,
+                            &_sfp_update_attr_soft_rs1,
+                            &(self->soft_rs1),
+                            "sfp_set_soft_rs1",
+                            show_err);
+}
+
+
+int
+__sfp_set_tx_eq(struct transvr_obj_s *self,
+                int input,
+                int show_e) {
+
+    int     err  = DEBUG_TRANSVR_INT_VAL;
+    char   *emsg = DEBUG_TRANSVR_STR_VAL;
+    uint8_t setv = DEBUG_TRANSVR_HEX_VAL;
+
+    if ((input < 0) || (input > 0xFF)) {
+        emsg = "input incorrect";
+        err = ERR_TRANSVR_BADINPUT;
+        goto err_sfp_set_tx_eq;
+    }
+    setv = (uint8_t)input;
+    if (self->tx_eq[0] == setv) {
+        return 0;
+    }
+    err = _common_set_uint8_attr(self,
+                                 self->eeprom_map_p->addr_tx_eq,
+                                 self->eeprom_map_p->page_tx_eq,
+                                 self->eeprom_map_p->offset_tx_eq,
+                                 setv,
+                                 &(self->tx_eq[0]),
+                                 "_sfp_set_tx_eq",
+                                 show_e);
+    if (err < 0) {
+        emsg = "set_uint8_attr fail";
+        goto err_sfp_set_tx_eq;
+    }
+    return 0;
+
+err_sfp_set_tx_eq:
+    if (show_e) {
+        SWPS_INFO("%s: %s <input>:%d\n", __func__, emsg, input);
+    }
+    return err;
+}
+
+
+int
+_sfp_set_tx_eq(struct transvr_obj_s *self,
+               int input,
+               int show_e) {
+
+    uint8_t tmp;
+    int i = 0;
+    int retry = 3;
+
+    for (i=0; i<retry; i++) {
+        if (__sfp_set_tx_eq(self, input, show_e) < 0){
+            continue;
+        }
+        tmp = self->tx_eq[0];
+        if (_sfp_update_attr_tx_eq(self, show_e) < 0){
+            continue;
+        }
+        if (self->tx_eq[0] == tmp){
+            return 0;
+        }
+    }
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+int
+sfp_set_tx_eq(struct transvr_obj_s *self,
+              int input) {
+
+    int err = _check_by_mode(self,
+                             &_sfp_update_attr_tx_eq,
+                             "sfp_set_tx_eq");
+    if (err < 0) {
+        SWPS_DEBUG("%s: check fail <err>:%d\n", __func__, err);
+        return err;
+    }
+    return _sfp_set_tx_eq(self, input, 1);
+}
+
+
+int
+__sfp_set_rx_em(struct transvr_obj_s *self,
+                int input,
+                int show_e) {
+
+    int     err  = DEBUG_TRANSVR_INT_VAL;
+    char   *emsg = DEBUG_TRANSVR_STR_VAL;
+    uint8_t setv = DEBUG_TRANSVR_HEX_VAL;
+
+    if ((input < 0) || (input > 0xFF)) {
+        emsg = "input incorrect";
+        err = ERR_TRANSVR_BADINPUT;
+        goto err_sfp_set_rx_em;
+    }
+    setv = (uint8_t)input;
+    if (self->rx_em[0] == setv) {
+        return 0;
+    }
+    err = _common_set_uint8_attr(self,
+                                 self->eeprom_map_p->addr_rx_em,
+                                 self->eeprom_map_p->page_rx_em,
+                                 self->eeprom_map_p->offset_rx_em,
+                                 setv,
+                                 &(self->rx_em[0]),
+                                 "_sfp_set_rx_em",
+                                 show_e);
+    if (err < 0) {
+        emsg = "set_uint8_attr fail";
+        goto err_sfp_set_rx_em;
+    }
+    return 0;
+
+err_sfp_set_rx_em:
+    if (show_e) {
+        SWPS_INFO("%s: %s <input>:%d\n", __func__, emsg, input);
+    }
+    return err;
+}
+
+
+int
+_sfp_set_rx_em(struct transvr_obj_s *self,
+               int input,
+               int show_e) {
+
+    uint8_t tmp;
+    int i = 0;
+    int retry = 3;
+
+    for (i=0; i<retry; i++) {
+        if (__sfp_set_rx_em(self, input, show_e) < 0){
+            continue;
+        }
+        tmp = self->rx_em[0];
+        if (_sfp_update_attr_rx_em(self, show_e) < 0){
+            continue;
+        }
+        if (self->rx_em[0] == tmp){
+            return 0;
+        }
+    }
+    return -1;
+}
+
+
+int
+sfp_set_rx_em(struct transvr_obj_s *self,
+              int input) {
+
+    int err = _check_by_mode(self,
+                             &_sfp_update_attr_rx_em,
+                             "sfp_set_rx_em");
+    if (err < 0) {
+        SWPS_DEBUG("%s: check fail <err>:%d\n", __func__, err);
+        return err;
+    }
+    return _sfp_set_rx_em(self, input, 1);
+}
+
+
+int
+sfp_set_1g_rj45_extphy_offset(struct transvr_obj_s *self,
+                              int input) {
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return ERR_TRANSVR_UNPLUGGED;
+    }
+    if ((self->info != TRANSVR_CLASS_BASE_T_1000) &&
+        (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    if ((input < 0) || (input > 0xff)) {
+        return ERR_TRANSVR_BADINPUT;
+    }
+    self->extphy_offset = (uint8_t)input;
+    return 0;
+}
+
+
+int
+sfp_set_1g_rj45_extphy_reg(struct transvr_obj_s *self,
+                           int input) {
+
+    int i      = 0;
+    int retry  = 3;
+    int delay  = 200;
+    uint16_t tmp = 0;
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return ERR_TRANSVR_UNPLUGGED;
+    }
+    if ((self->info != TRANSVR_CLASS_BASE_T_1000) &&
+        (self->info != TRANSVR_CLASS_BASE_T_1000_up) ){
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    if ((input < 0) || (input > 0xffff)) {
+        return ERR_TRANSVR_BADINPUT;
+    }
+    tmp = ((input & 0x00ff) << 8) | ((input & 0xff00) >> 8);
+    if (_common_setup_page(self, VAL_TRANSVR_EXTPHY_ADDR_56,
+                           -1, self->extphy_offset, 1, 0) < 0) {
+        return -EIO;
+    }
+    for (i=0; i<=retry; i++) {
+        if (i2c_smbus_write_word_data(self->i2c_client_p,
+                                      self->extphy_offset,
+                                      tmp) >= 0) {
+            return 0;
+        }
+        msleep(delay);
+    }
+    SWPS_INFO("%s: retry:%d fail <port>:%s <offset>:0x%02x\n",
+              __func__, retry, self->swp_name, self->extphy_offset);
+    return -EIO;
+}
+
+
+static int
+__qsfp_set_cdr(struct transvr_obj_s *self,
+               int input_val,
+               int show_err) {
+
+    uint8_t update_val;
+    int CDR_FEATURE_SUPPORTED = 0x3;
+    int retval    = ERR_TRANSVR_UNEXCPT;
+    int err_code  = ERR_TRANSVR_UNEXCPT;
+    char *err_msg = DEBUG_TRANSVR_STR_VAL;
+    char *func_name = "__qsfp_set_cdr";
+
+    /* Check input value */
+    if ((input_val < 0) || (input_val > 0xff)){
+        retval   = ERR_TRANSVR_BADINPUT;
+        err_code = ERR_TRANSVR_BADINPUT;
+        err_msg  = "Input range incorrect!";
+        goto err_qsfp_set_cdr_1;
+    }
+    update_val = (uint8_t)input_val;
+    /* Check CDR supported by transceiver */
+    err_code = qsfp_get_cdr_present(self);
+    if (err_code < 0) {
+        retval   = err_code;
+        switch (err_code) {
+            case ERR_TRANSVR_UNINIT:
+                err_msg  = "Check CDR present fail!";
+                break;
+            case ERR_TRANSVR_UNPLUGGED:
+                err_msg  = "Transceiver unplugged!";
+                break;
+            default:
+                err_msg  = "Check CDR present fail!";
+                break;
+        }
+        goto err_qsfp_set_cdr_1;
+    }
+    if (err_code != CDR_FEATURE_SUPPORTED) {
+        retval   = ERR_TRANSVR_NOTSUPPORT;
+        err_msg  = "This transceiver not support CDR!";
+        goto err_qsfp_set_cdr_1;
+    }
+    /* Check and update */
+    err_code = _check_by_mode(self,
+                              &_qsfp_update_attr_cdr,
+                              func_name);
+    if ( (err_code < 0) ||
+         (self->cdr == DEBUG_TRANSVR_HEX_VAL) ){
+        retval   = err_code;
+        err_msg  = "Get current value fail!";
+        goto err_qsfp_set_cdr_1;
+    }
+    /* Write input value to transceiver */
+    return _common_set_uint8_attr(self,
+                                  self->eeprom_map_p->addr_cdr,
+                                  self->eeprom_map_p->page_cdr,
+                                  self->eeprom_map_p->offset_cdr,
+                                  update_val,
+                                  &(self->cdr),
+                                  func_name,
+                                  show_err);
+
+err_qsfp_set_cdr_1:
+    if (show_err) {
+        SWPS_INFO("%s: %s <ERR>:%d <Port>:%s\n <Input>:%d\n",
+                  __func__, err_msg, err_code, self->swp_name, input_val);
+    }
+    return retval;
+}
+
+
+int
+qsfp_set_cdr(struct transvr_obj_s *self,
+             int input_val) {
+    return __qsfp_set_cdr(self, input_val, 1);
+}
+
+
+int
+qsfp_set_soft_tx_disable(struct transvr_obj_s *self,
+                         int input_val) {
+
+    int show_err     = 1;
+    int in_max       = 0xf; /* 1111 */
+    int in_min       = 0x0; /* 0000 */
+    int retval       = DEBUG_TRANSVR_INT_VAL;
+    int update_val   = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    retval = _check_by_mode(self,
+                            &_qsfp_update_attr_soft_tx_disable,
+                            "qsfp_set_soft_tx_disable");
+    if (retval < 0) {
+        snprintf(err_msg, 63, "Not ready. err:%d", retval);
+        goto err_qsfp_set_soft_tx_disable;
+    }
+    if ((input_val > in_max) ||
+        (input_val < in_min) ){
+        retval = ERR_TRANSVR_BADINPUT;
+        snprintf(err_msg, 63, "Input value:%d incorrect!", input_val);
+        goto err_qsfp_set_soft_tx_disable;
+    }
+    if ((self->tx_disable & 0x0f) == input_val) {
+        return 0;
+    }
+    update_val = ((self->tx_disable & 0xf0) & input_val);
+    retval = _common_set_uint8_attr(self,
+                                    self->eeprom_map_p->addr_tx_disable,
+                                    self->eeprom_map_p->page_tx_disable,
+                                    self->eeprom_map_p->offset_tx_disable,
+                                    input_val,
+                                    &(self->tx_disable),
+                                    "qsfp_set_tx_disable",
+                                    show_err);
+    if (retval < 0) {
+        snprintf(err_msg, 63, "_common_set_uint8_attr:%d fail!", retval);
+        goto err_qsfp_set_soft_tx_disable;
+    }
+    return 0;
+
+err_qsfp_set_soft_tx_disable:
+    SWPS_INFO("%s: %s <port>:%s\n", __func__, err_msg, self->swp_name);
+    return retval;
+}
+
+
+int
+_qsfp_set_auto_tx_disable(struct transvr_obj_s *self,
+                          uint8_t update) {
+
+    uint8_t tx_enable = 0x0;
+    int show_e = 1;
+    int err    = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    /* Handle timing issues */
+    if (update != tx_enable) {
+        /* Note:
+         *  Because there are some txvr has timing issues,
+         *  therefore we need to execute reset cycle first.
+         *  (enable -> other settings)
+          */
+        err = _common_set_uint8_attr(self,
+                                     self->eeprom_map_p->addr_tx_disable,
+                                     self->eeprom_map_p->page_tx_disable,
+                                     self->eeprom_map_p->offset_tx_disable,
+                                     tx_enable,
+                                     &(self->tx_disable),
+                                     "_qsfp_set_auto_tx_disable",
+                                     show_e);
+        if (err < 0) {
+            emsg = "I2C set reset value fail";
+            goto err_qsfp_set_auto_tx_disable;
+        }
+        mdelay(10);
+    }
+    /* Setup target value */
+    err = _common_set_uint8_attr(self,
+                                 self->eeprom_map_p->addr_tx_disable,
+                                 self->eeprom_map_p->page_tx_disable,
+                                 self->eeprom_map_p->offset_tx_disable,
+                                 self->auto_tx_disable,
+                                 &(self->tx_disable),
+                                 "_qsfp_set_auto_tx_disable",
+                                 show_e);
+    if (err < 0) {
+        emsg = "I2C set target value fail";
+        goto err_qsfp_set_auto_tx_disable;
+    }
+    /* Check and update */
+    err = _common_update_uint8_attr(self,
+                                    self->eeprom_map_p->addr_tx_disable,
+                                    self->eeprom_map_p->page_tx_disable,
+                                    self->eeprom_map_p->offset_tx_disable,
+                                    self->eeprom_map_p->length_tx_disable,
+                                    &(self->tx_disable),
+                                    "_qsfp_set_auto_tx_disable",
+                                    show_e);
+    if (err < 0) {
+        emsg = "I2C get value fail";
+        goto err_qsfp_set_auto_tx_disable;
+    }
+    if (self->tx_disable != update) {
+        emsg = "data not become effective";
+        goto err_qsfp_set_auto_tx_disable;
+    }
+    return 0;
+
+err_qsfp_set_auto_tx_disable:
+    SWPS_DEBUG("%s: %s <port>:%s\n",
+               __func__, emsg, self->swp_name);
+    return ERR_TRANSVR_UPDATE_FAIL;
+}
+
+
+int
+qsfp_set_auto_tx_disable(struct transvr_obj_s *self,
+                         int input_val) {
+
+    int in_max = 0xf; /* 1111 */
+    int in_min = 0x0; /* 0000 */
+    int retval = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    /* Update settings*/
+    if (input_val == VAL_TRANSVR_FUNCTION_DISABLE) {
+        emsg = "User disable auto tx_disable";
+        self->auto_tx_disable = VAL_TRANSVR_FUNCTION_DISABLE;
+        goto out_qsfp_set_auto_tx_disable;
+    }
+    if ((input_val > in_max) || (input_val < in_min) ){
+        SWPS_INFO("%s: Input value:%d incorrect! <port>:%s\n",
+                  __func__, input_val, self->swp_name);
+        return ERR_TRANSVR_BADINPUT;
+    }
+    self->auto_tx_disable = input_val;
+    /* Check current soft tx_disable */
+    retval = _check_by_mode(self,
+                            &_qsfp_update_attr_soft_tx_disable,
+                            "qsfp_set_auto_tx_disable");
+    switch (retval) {
+        case 0:
+            break;
+        case ERR_TRANSVR_UNPLUGGED:
+            emsg = "Doesn't need to update";
+            goto out_qsfp_set_auto_tx_disable;
+        default:
+            SWPS_INFO("%s: setup fail <err>:%d <port>:%s\n",
+                      __func__, retval, self->swp_name);
+            return retval;
+    }
+    return _qsfp_set_auto_tx_disable(self, input_val);
+
+out_qsfp_set_auto_tx_disable:
+    SWPS_DEBUG("%s: %s <port>:%s <input>:%d\n <ret>:%d",
+               __func__, emsg, self->swp_name, input_val, retval);
+    return 0;
+}
+
+
+int
+__qsfp_set_tx_eq(struct transvr_obj_s *self,
+                 int input,
+                 int show_e) {
+    /* [Note]
+     *   0x<CH-1><CH-2><CH-3><CH-4>
+     */
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+    uint8_t setv[2] = {0x00, 0x00};
+
+    if ((input < 0) || (input > 0xFFFF)) {
+        emsg = "input incorrect";
+        err = ERR_TRANSVR_BADINPUT;
+        goto err_qsfp_set_tx_eq;
+    }
+    setv[0] = (uint8_t)((input & 0xFF00) >> 8);
+    setv[1] = (uint8_t)(input & 0xFF);
+    if ((self->tx_eq[0] == setv[0]) &&
+        (self->tx_eq[1] == setv[1]) ) {
+        return 0;
+    }
+    err = _common_set_uint8_array(self,
+                                  self->eeprom_map_p->addr_tx_eq,
+                                  self->eeprom_map_p->page_tx_eq,
+                                  self->eeprom_map_p->offset_tx_eq,
+                                  self->eeprom_map_p->length_tx_eq,
+                                  setv,
+                                  self->tx_eq,
+                                  "_qsfp_set_tx_eq",
+                                  show_e);
+    if (err < 0) {
+        emsg = "set_uint8_array fail";
+        goto err_qsfp_set_tx_eq;
+    }
+    return 0;
+
+err_qsfp_set_tx_eq:
+    if (show_e) {
+        SWPS_INFO("%s: %s <input>:%d\n", __func__, emsg, input);
+    }
+    return err;
+}
+
+
+int
+_qsfp_set_tx_eq(struct transvr_obj_s *self,
+                int input,
+                int show_e) {
+
+    int i = 0;
+    int retry = 3;
+    uint8_t tmp[2];
+
+    for (i=0; i<retry; i++) {
+        if (__qsfp_set_tx_eq(self, input, show_e) < 0){
+            continue;
+        }
+        tmp[0] = self->tx_eq[0];
+        tmp[1] = self->tx_eq[1];
+        if (_qsfp_update_attr_tx_eq(self, show_e) < 0){
+            continue;
+        }
+        if ((self->tx_eq[0] == tmp[0]) &&
+            (self->tx_eq[1] == tmp[1]) ){
+            return 0;
+        }
+    }
+    return -1;
+}
+
+
+int
+qsfp_set_tx_eq(struct transvr_obj_s *self,
+               int input) {
+
+    int err = _check_by_mode(self,
+                             &_qsfp_update_attr_tx_eq,
+                             "qsfp_set_tx_eq");
+    if (err < 0) {
+        SWPS_DEBUG("%s: check fail <err>:%d\n", __func__, err);
+        return err;
+    }
+    return _qsfp_set_tx_eq(self, input, 1);
+}
+
+
+int
+__qsfp_set_rx_am(struct transvr_obj_s *self,
+                 int input,
+                 int show_e) {
+    /* [Note]
+     *   0x<CH-1><CH-2><CH-3><CH-4>
+     */
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+    uint8_t setv[2] = {0x00, 0x00};
+
+    if ((input < 0) || (input > 0xFFFF)) {
+        emsg = "input incorrect";
+        err = ERR_TRANSVR_BADINPUT;
+        goto err_qsfp_set_rx_am;
+    }
+    setv[0] = (uint8_t)((input & 0xFF00) >> 8);
+    setv[1] = (uint8_t)(input & 0xFF);
+    if ((self->rx_am[0] == setv[0]) &&
+        (self->rx_am[1] == setv[1]) ) {
+        return 0;
+    }
+    err = _common_set_uint8_array(self,
+                                  self->eeprom_map_p->addr_rx_am,
+                                  self->eeprom_map_p->page_rx_am,
+                                  self->eeprom_map_p->offset_rx_am,
+                                  self->eeprom_map_p->length_rx_am,
+                                  setv,
+                                  self->rx_am,
+                                  "_qsfp_set_rx_am",
+                                  show_e);
+    if (err < 0) {
+        emsg = "set_uint8_array fail";
+        goto err_qsfp_set_rx_am;
+    }
+    return 0;
+
+err_qsfp_set_rx_am:
+    if (show_e) {
+        SWPS_INFO("%s: %s <input>:%d\n", __func__, emsg, input);
+    }
+    return err;
+}
+
+
+int
+_qsfp_set_rx_am(struct transvr_obj_s *self,
+                int input,
+                int show_e) {
+
+    int i = 0;
+    int retry = 3;
+    uint8_t tmp[2];
+
+    for (i=0; i<retry; i++) {
+        if (__qsfp_set_rx_am(self, input, show_e) < 0){
+            continue;
+        }
+        tmp[0] = self->rx_am[0];
+        tmp[1] = self->rx_am[1];
+        if (_qsfp_update_attr_rx_am(self, show_e) < 0){
+            continue;
+        }
+        if ((self->rx_am[0] == tmp[0]) &&
+            (self->rx_am[1] == tmp[1]) ){
+            return 0;
+        }
+    }
+    return -1;
+}
+
+
+int
+qsfp_set_rx_am(struct transvr_obj_s *self,
+               int input) {
+
+    int err = _check_by_mode(self,
+                             &_qsfp_update_attr_rx_am,
+                             "qsfp_set_rx_am");
+    if (err < 0) {
+        SWPS_DEBUG("%s: check fail <err>:%d\n", __func__, err);
+        return err;
+    }
+    return _qsfp_set_rx_am(self, input, 1);
+}
+
+
+int
+__qsfp_set_rx_em(struct transvr_obj_s *self,
+                 int input,
+                 int show_e) {
+    /* [Note]
+     *   0x<CH-1><CH-2><CH-3><CH-4>
+     */
+    int   err  = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+    uint8_t setv[2] = {0x00, 0x00};
+
+    if ((input < 0) || (input > 0xFFFF)) {
+        emsg = "input incorrect";
+        err = ERR_TRANSVR_BADINPUT;
+        goto err_qsfp_set_rx_em;
+    }
+    setv[0] = (uint8_t)((input & 0xFF00) >> 8);
+    setv[1] = (uint8_t)(input & 0xFF);
+    if ((self->rx_em[0] == setv[0]) &&
+        (self->rx_em[1] == setv[1]) ) {
+        return 0;
+    }
+    err = _common_set_uint8_array(self,
+                                  self->eeprom_map_p->addr_rx_em,
+                                  self->eeprom_map_p->page_rx_em,
+                                  self->eeprom_map_p->offset_rx_em,
+                                  self->eeprom_map_p->length_rx_em,
+                                  setv,
+                                  self->rx_em,
+                                  "_qsfp_set_rx_em",
+                                  show_e);
+    if (err < 0) {
+        emsg = "set_uint8_array fail";
+        goto err_qsfp_set_rx_em;
+    }
+    return 0;
+
+err_qsfp_set_rx_em:
+    if (show_e) {
+        SWPS_INFO("%s: %s <input>:%d\n", __func__, emsg, input);
+    }
+    return err;
+}
+
+
+int
+_qsfp_set_rx_em(struct transvr_obj_s *self,
+                int input,
+                int show_e) {
+
+    int i = 0;
+    int retry = 3;
+    uint8_t tmp[2];
+
+    for (i=0; i<retry; i++) {
+        if (__qsfp_set_rx_em(self, input, show_e) < 0){
+            continue;
+        }
+        tmp[0] = self->rx_em[0];
+        tmp[1] = self->rx_em[1];
+        if (_qsfp_update_attr_rx_em(self, show_e) < 0){
+            continue;
+        }
+        if ((self->rx_em[0] == tmp[0]) &&
+            (self->rx_em[1] == tmp[1]) ){
+            return 0;
+        }
+    }
+    return -1;
+}
+
+
+int
+qsfp_set_rx_em(struct transvr_obj_s *self,
+               int input) {
+
+    int err = _check_by_mode(self,
+                             &_qsfp_update_attr_rx_em,
+                             "qsfp_set_rx_em");
+    if (err < 0) {
+        SWPS_DEBUG("%s: check fail <err>:%d\n", __func__, err);
+        return err;
+    }
+    return _qsfp_set_rx_em(self, input, 1);
+}
+
+
+int
+common_transvr_dump(struct transvr_obj_s* self){
+
+    char *type_name = "Undefined";
+
+    if (TRANSVR_INFO_DUMP_ENABLE != 1) {
+        return 0;
+    }
+    switch (self->type) {
+        case TRANSVR_TYPE_SFP:
+            type_name = STR_TRANSVR_SFP;
+            break;
+        case TRANSVR_TYPE_QSFP:
+            type_name = STR_TRANSVR_QSFP;
+            break;
+        case TRANSVR_TYPE_QSFP_PLUS:
+            type_name = STR_TRANSVR_QSFP_PLUS;
+            break;
+        case TRANSVR_TYPE_QSFP_28:
+            type_name = STR_TRANSVR_QSFP28;
+            break;
+        case TRANSVR_TYPE_FAKE:
+            type_name = "FAKE";
+            goto ok_common_transvr_dump;
+        case TRANSVR_TYPE_UNPLUGGED:
+            type_name = "UNPLUGGED";
+            goto err_common_transvr_dump;
+        case TRANSVR_TYPE_INCONSISTENT:
+            type_name = "INCONSISTENT";
+            goto err_common_transvr_dump;
+        case TRANSVR_TYPE_ERROR:
+            type_name = "ERROR";
+            goto err_common_transvr_dump;
+
+        default:
+            type_name = "UNEXPECTED";
+            goto err_common_transvr_dump;
+    }
+    printk(KERN_INFO "[SWPS] Dump %s information:\n", self->swp_name);
+    printk(KERN_INFO "       |- <Type>:%s\n", type_name);
+    printk(KERN_INFO "       |- <VenderName>:%s\n", self->vendor_name);
+    printk(KERN_INFO "       |- <VenderPN>:%s\n", self->vendor_pn);
+    printk(KERN_INFO "       |- <VenderREV>:%s\n", self->vendor_rev);
+    printk(KERN_INFO "       |- <VenderSN>:%s\n", self->vendor_sn);
+    printk(KERN_INFO "       |- <BitRate>:0x%02x\n", self->br);
+    printk(KERN_INFO "       |- <RevComp>:0x%02x\n", self->comp_rev);
+    printk(KERN_INFO "       |- <LenOM1>:%d\n", self->len_om1);
+    printk(KERN_INFO "       |- <LenOM2>:%d\n", self->len_om2);
+    printk(KERN_INFO "       |- <LenOM3>:%d\n", self->len_om3);
+    printk(KERN_INFO "       |- <LenOM4>:%d\n", self->len_om4);
+    return 0;
+
+ok_common_transvr_dump:
+    SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name);
+    return 0;
+
+err_common_transvr_dump:
+    SWPS_INFO("%s: %s is %s\n", __func__, self->swp_name, type_name);
+    return -1;
+}
+
+
+int
+sfp_transvr_dump(struct transvr_obj_s* self) {
+
+    if (TRANSVR_INFO_DUMP_ENABLE != 1) {
+        return 0;
+    }
+    if (common_transvr_dump(self) < 0) {
+        return -1;
+    }
+    printk(KERN_INFO "       |- <LenSM>:%d\n", self->len_sm);
+    printk(KERN_INFO "       |- <LenSMF>:%d\n", self->len_smf);
+    printk(KERN_INFO "       '- <RateID>:0x%02x\n", self->rate_id);
+    return 0;
+}
+
+
+int
+qsfp_transvr_dump(struct transvr_obj_s* self) {
+
+    if (TRANSVR_INFO_DUMP_ENABLE != 1) {
+        return 0;
+    }
+    if (common_transvr_dump(self) < 0) {
+        return -1;
+    }
+    printk(KERN_INFO "       |- <LenSMF>:%d\n", self->len_smf);
+    printk(KERN_INFO "       '- <PowerClass>:Class_%d\n", __qsfp_get_power_cls(self, 0));
+    return 0;
+}
+
+
+int
+fake_transvr_dump(struct transvr_obj_s* self) {
+
+    printk(KERN_INFO "[SWPS] Dump transceiver information: %s\n", self->swp_name);
+    printk(KERN_INFO "       |- <Type>:FAKE\n");
+    printk(KERN_INFO "       |- <VenderName>:FAKE_VENDER_NAME\n");
+    printk(KERN_INFO "       |- <VenderPN>:FAKE_VENDER_PN\n");
+    printk(KERN_INFO "       |- <VenderREV>:FAKE_VENDER_REV\n");
+    printk(KERN_INFO "       |- <VenderSN>:FAKE_VENDER_SN\n");
+    printk(KERN_INFO "       |- <BitRate>:0x99\n");
+    printk(KERN_INFO "       |- <LenOM1>:99\n");
+    printk(KERN_INFO "       |- <LenOM2>:99\n");
+    printk(KERN_INFO "       |- <LenOM3>:99\n");
+    printk(KERN_INFO "       |- <LenOM4>:99\n");
+    printk(KERN_INFO "       |- <LenSM>:99\n");
+    printk(KERN_INFO "       |- <LenSMF>:99\n");
+    printk(KERN_INFO "       '- <RevComp>:0x99\n");
+    return 0;
+}
+
+
+/* ========== Object functions for fake type ==========
+ */
+int
+fake_transvr_update(struct transvr_obj_s *self,
+                    int show_err){
+    self->state = STATE_TRANSVR_CONNECTED;
+    return 0;
+}
+
+
+int
+fake_get_binary(struct transvr_obj_s *self){
+    return 1;
+}
+
+int
+fake_get_int(struct transvr_obj_s *self){
+    return 99;
+}
+
+
+int
+fake_get_hex(struct transvr_obj_s *self){
+    return 0x0f;
+}
+
+
+int
+fake_get_str(struct transvr_obj_s *self, char *buf) {
+    return snprintf(buf, 16, "fake_get_str\n");
+}
+
+
+int
+fake_set_int(struct transvr_obj_s *self, int input){
+    SWPS_INFO("%s: %d\n", __func__, input);
+    return 0;
+}
+
+
+int
+fake_set_hex(struct transvr_obj_s *self, int input){
+    SWPS_INFO("%s: 0x%02x\n", __func__, input);
+    return 0;
+}
+
+
+/* ========== Object functions for unsupported ==========
+ */
+int
+unsupported_get_func(struct transvr_obj_s *self){
+    return ERR_TRANSVR_NOTSUPPORT;
+}
+
+
+int
+unsupported_get_func2(struct transvr_obj_s *self,
+                      char *buf_p) {
+    int len = snprintf(buf_p, 8, "%d\n", ERR_TRANSVR_NOTSUPPORT);
+    return len;
+}
+
+
+int
+unsupported_set_func(struct transvr_obj_s *self,
+                     int input_val){
+    return ERR_TRANSVR_NOTSUPPORT;
+}
+
+
+
+/* ========== Object functions for long term task ==========
+ *
+ * [Note]
+ *   SWPS transceiver worker is likely the green-thread (coroutine).
+ *   Due to resource and performance considerations. SWPS run all
+ *   features in one kthread at the same time, and handle by it self.
+ */
+
+/* For Transceiver Task Handling
+ */
+static struct transvr_worker_s *
+transvr_task_get(struct transvr_obj_s *self,
+                 char *func_name) {
+
+    struct transvr_worker_s *curr_p = self->worker_p;
+
+    while(curr_p != NULL){
+        if (strcmp((curr_p->func_name), func_name) == 0 ) {
+            return curr_p;
+        }
+        curr_p = curr_p->next_p;
+    }
+    return NULL;
+}
+
+
+static struct transvr_worker_s*
+transvr_task_creat(struct transvr_obj_s *self,
+                   int (*main_task)(struct transvr_worker_s *task),
+                   int (*post_task)(struct transvr_worker_s *task),
+                   char *caller) {
+
+    struct transvr_worker_s *task_p = NULL;
+    struct transvr_worker_s *curr_p = NULL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    /* Check task not exist */
+    task_p = transvr_task_get(self, caller);
+    if (task_p) {
+        snprintf(err_msg, sizeof(err_msg), "Task already created!");
+        goto err_transvr_task_creat;
+    }
+    /* Create task worker */
+    task_p = kzalloc(sizeof(struct transvr_worker_s), GFP_KERNEL);
+    if (!task_p){
+        snprintf(err_msg, sizeof(err_msg), "kzalloc fail");
+        goto err_transvr_task_creat;
+    }
+    /* Setup task data */
+    task_p->transvr_p    = self;
+    task_p->next_p       = NULL;
+    task_p->trigger_time = 0;
+    task_p->retry        = 1;
+    task_p->state        = STATE_T_TASK_INIT;
+    task_p->main_task    = main_task;
+    task_p->post_task    = post_task;
+    task_p->p_data       = NULL;
+    snprintf(task_p->func_name, sizeof(task_p->func_name), "%s", caller);
+    /* Setup Link List */
+    if (self->worker_p) {
+        curr_p = self->worker_p;
+        while(curr_p->next_p != NULL) {
+            curr_p = curr_p->next_p;
+        }
+        curr_p->next_p = task_p;
+        task_p->pre_p  = curr_p;
+    } else {
+        self->worker_p = task_p;
+        task_p->pre_p  = NULL;
+    }
+    return task_p;
+
+err_transvr_task_creat:
+    SWPS_ERR("%s: %s <caller>:%s <port>:%s\n",
+            __func__, err_msg, caller, self->swp_name);
+    return NULL;
+}
+
+
+static void
+transvr_task_free_one(struct transvr_worker_s *task_p){
+
+    struct transvr_worker_s *pre_p  = NULL;
+    struct transvr_worker_s *next_p = NULL;
+
+    if (task_p) {
+        pre_p  = task_p->pre_p;
+        next_p = task_p->next_p;
+
+        if ((pre_p) && (next_p)) {
+            pre_p->next_p = next_p;
+            next_p->pre_p = pre_p;
+
+        } else if ((!pre_p) && (next_p)) {
+            next_p->pre_p = NULL;
+
+        } else if ((pre_p) && (!next_p)) {
+            pre_p->next_p = NULL;
+
+        } else if ((!pre_p) && (!next_p)) {
+            task_p->transvr_p->worker_p = NULL;
+        } else {
+            SWPS_ERR("%s: Unexcept case!\n <port>:%s",
+                    __func__, task_p->transvr_p->swp_name);
+        }
+        kfree(task_p->p_data);
+        kfree(task_p);
+    }
+}
+
+
+static void
+transvr_task_free_all(struct transvr_obj_s *self) {
+
+    struct transvr_worker_s *curr_p = NULL;
+    struct transvr_worker_s *next_p = NULL;
+
+    if (self->worker_p) {
+        curr_p = self->worker_p;
+        while(curr_p) {
+            next_p = curr_p->next_p;
+            transvr_task_free_one(curr_p);
+            curr_p = next_p;
+        }
+        self->worker_p = NULL;
+    }
+}
+
+
+static void
+transvr_cache_free_all(struct transvr_obj_s *self) {
+
+    memset(self->vendor_name, 0, (LEN_TRANSVR_M_STR * sizeof(char)) );
+    memset(self->vendor_rev,  0, (LEN_TRANSVR_M_STR * sizeof(char)) );
+    memset(self->vendor_pn,   0, (LEN_TRANSVR_M_STR * sizeof(char)) );
+    memset(self->vendor_sn,   0, (LEN_TRANSVR_M_STR * sizeof(char)) );
+    self->extphy_offset = 0;
+}
+
+static int
+_transvr_task_run_main(struct transvr_worker_s *task_p) {
+
+    int retval = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64]  = DEBUG_TRANSVR_STR_VAL;
+
+    if (!task_p){
+        snprintf(err_msg, sizeof(err_msg), "main_task is NULL!");
+        goto main_transvr_task_err;
+    }
+    if ((task_p->trigger_time) == 0){
+        goto main_transvr_task_run;
+    }
+    if (time_before(jiffies, task_p->trigger_time)){
+        goto main_transvr_task_wait;
+    }
+    goto main_transvr_task_run;
+
+main_transvr_task_run:
+    if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) {
+        task_p->retry -= 1;
+    }
+    retval = task_p->main_task(task_p);
+    if (retval < 0) {
+        if (task_p->retry > 0) {
+            task_p->state = STATE_T_TASK_WAIT;
+            return EVENT_TRANSVR_TASK_WAIT;
+        }
+        snprintf(err_msg, sizeof(err_msg), "Run main_task fail!");
+        goto main_transvr_task_err;
+    }
+    goto main_transvr_task_identify;
+
+main_transvr_task_identify:
+    switch (retval) {
+        case EVENT_TRANSVR_TASK_WAIT:
+            task_p->state = STATE_T_TASK_WAIT;
+            return EVENT_TRANSVR_TASK_WAIT;
+
+        case EVENT_TRANSVR_TASK_DONE:
+            task_p->state = STATE_T_TASK_DONE;
+            return EVENT_TRANSVR_TASK_DONE;
+
+    default:
+        break;
+    }
+    snprintf(err_msg, sizeof(err_msg), "Run main_task fail!");
+    goto main_transvr_task_err;
+
+main_transvr_task_wait:
+    task_p->state = STATE_T_TASK_WAIT;
+    return EVENT_TRANSVR_TASK_WAIT;
+
+main_transvr_task_err:
+    task_p->state = STATE_T_TASK_FAIL;
+    SWPS_INFO("%s: %s <rval>:%d <port>:%s\n",
+            __func__, err_msg, retval, task_p->transvr_p->swp_name);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+static int
+_transvr_task_run_post(struct transvr_worker_s *task_p) {
+
+    char err_msg[64]  = DEBUG_TRANSVR_STR_VAL;
+
+    if ((task_p->post_task) == NULL) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    switch (task_p->state) {
+        case STATE_T_TASK_WAIT:
+        case STATE_T_TASK_INIT:
+            goto post_transvr_task_wait;
+
+        case STATE_T_TASK_DONE:
+        case STATE_T_TASK_FAIL:
+            goto post_transvr_task_run;
+
+    default:
+        break;
+    }
+    snprintf(err_msg, sizeof(err_msg), "Unexcept task state");
+    goto post_transvr_task_err;
+
+post_transvr_task_run:
+    task_p->post_task(task_p);
+    return EVENT_TRANSVR_TASK_DONE;
+
+post_transvr_task_wait:
+    return EVENT_TRANSVR_TASK_WAIT;
+
+post_transvr_task_err:
+    SWPS_INFO("%s: %s <state>:%d <port>:%s\n",
+              __func__, err_msg, task_p->state, task_p->transvr_p->swp_name);
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+static int
+transvr_task_run_one(struct transvr_worker_s *task_p) {
+
+    int retval_main  = DEBUG_TRANSVR_INT_VAL;
+    int retval_post  = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    retval_main = _transvr_task_run_main(task_p);
+    if (retval_main < 0) {
+        snprintf(err_msg, sizeof(err_msg), "Execute main_task fail!");
+        goto err_transvr_task_run_one;
+    }
+    retval_post = _transvr_task_run_post(task_p);
+    if (retval_post < 0) {
+        snprintf(err_msg, sizeof(err_msg), "Execute post_task fail!");
+        goto err_transvr_task_run_one;
+    }
+    return retval_main;
+
+err_transvr_task_run_one:
+    SWPS_INFO("%s: %s <main>:%d <post>:%d <caller>:%s <port>:%s\n",
+              __func__, err_msg, retval_main, retval_post,
+              task_p->func_name, task_p->transvr_p->swp_name);
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+static int
+transvr_task_run_all(struct transvr_obj_s *self) {
+
+    int haserr = 0;
+    int retval = DEBUG_TRANSVR_INT_VAL;
+    struct transvr_worker_s *curr_p = NULL;
+    struct transvr_worker_s *next_p = NULL;
+
+    if ((self->worker_p) == NULL) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    curr_p = self->worker_p;
+    while (curr_p != NULL) {
+        next_p = curr_p->next_p;
+        retval = transvr_task_run_one(curr_p);
+        if (curr_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) {
+            curr_p = next_p;
+            continue;
+        }
+        switch (retval) {
+            case EVENT_TRANSVR_TASK_WAIT:
+                break;
+            case EVENT_TRANSVR_TASK_DONE:
+                transvr_task_free_one(curr_p);
+                break;
+            case EVENT_TRANSVR_TASK_FAIL:
+
+            default:
+                haserr = 1;
+                transvr_task_free_one(curr_p);
+                break;
+        }
+        curr_p = next_p;
+    }
+    if (haserr) {
+        return EVENT_TRANSVR_TASK_FAIL;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+static void
+transvr_task_set_delay(struct transvr_worker_s *task_p,
+                       unsigned long delay_msec) {
+
+    task_p->trigger_time = (jiffies + (delay_msec * (HZ/1000)));
+}
+
+
+static void
+transvr_task_set_retry(struct transvr_worker_s *task_p,
+                       unsigned long retry_times) {
+
+    task_p->retry = retry_times;
+}
+
+
+/* For Transceiver Post Task
+ */
+int
+taskfunc_post_do_nothing(struct transvr_worker_s *task_p) {
+
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+taskfunc_post_handle_task_state(struct transvr_worker_s *task_p) {
+
+    struct transvr_obj_s* tp = task_p->transvr_p;
+
+    switch (task_p->state) {
+        case STATE_T_TASK_INIT:
+        case STATE_T_TASK_WAIT:
+            return EVENT_TRANSVR_TASK_WAIT;
+
+        case STATE_T_TASK_DONE:
+            tp->state = STATE_TRANSVR_CONNECTED;
+            tp->send_uevent(tp, KOBJ_ADD);
+            return EVENT_TRANSVR_TASK_DONE;
+
+        case STATE_T_TASK_FAIL:
+            tp->state = STATE_TRANSVR_UNEXCEPTED;
+            return EVENT_TRANSVR_TASK_FAIL;
+
+        default:
+            break;
+    }
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+/* For Transceiver Main Task
+ */
+int
+_taskfunc_sfp_setup_soft_rs(struct transvr_worker_s *task_p,
+                            int input_val,
+                            int address,
+                            int page,
+                            int offset,
+                            int bit_shift,
+                            uint8_t *attr_p,
+                            char *caller) {
+
+    int show_err = 0;
+    int err_code = DEBUG_TRANSVR_INT_VAL;
+    char *err_str  = DEBUG_TRANSVR_STR_VAL;
+    char *func_str = "_taskfunc_sfp_setup_soft_rs";
+
+    err_code = _sfp_update_attr_soft_rs0(task_p->transvr_p, 0);
+    if (err_code < 0) {
+        err_str = "Get current soft_rs0 fail!";
+        goto err_taskfunc_sfp_setup_soft_rs_1;
+    }
+    err_code = __sfp_set_soft_rs(task_p->transvr_p,
+                                 input_val,
+                                 address,
+                                 page,
+                                 offset,
+                                 bit_shift,
+                                 attr_p,
+                                 caller,
+                                 show_err);
+    if (err_code < 0) {
+        err_str = "Get current soft_rs0 fail!";
+        goto err_taskfunc_sfp_setup_soft_rs_1;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_sfp_setup_soft_rs_1:
+    if ((task_p->retry) == 0) {
+        SWPS_INFO("%s: %s <port>:%s <input>:%d <err>:%d\n",
+                  func_str, err_str, task_p->transvr_p->swp_name, input_val, err_code);
+    }
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+__taskfunc_sfp_setup_hard_rs(struct transvr_worker_s *task_p,
+                             int input_val,
+                             int (*get_func)(struct ioexp_obj_s *self, int virt_offset),
+                             int (*set_func)(struct ioexp_obj_s *self, int virt_offset, int input_val)) {
+
+    int err_val    = EVENT_TRANSVR_EXCEP_EXCEP;
+    char *err_str  = DEBUG_TRANSVR_STR_VAL;
+
+    err_val = get_func(task_p->transvr_p->ioexp_obj_p,
+                       task_p->transvr_p->ioexp_virt_offset);
+
+    if (err_val < 0) {
+        if (err_val == ERR_IOEXP_NOTSUPPORT) {
+            return EVENT_TRANSVR_TASK_DONE;
+        }
+        err_str = "Get current hard_rs fail!";
+        goto err_p_taskfunc_sfp_setup_hard_rs_1;
+    }
+    if (err_val == input_val) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    err_val = set_func(task_p->transvr_p->ioexp_obj_p,
+                       task_p->transvr_p->ioexp_virt_offset,
+                       input_val);
+    if (err_val < 0) {
+        err_str = "Setup hard_rs fail!";
+        goto err_p_taskfunc_sfp_setup_hard_rs_1;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_p_taskfunc_sfp_setup_hard_rs_1:
+    if ((task_p->retry) == 0) {
+        SWPS_INFO("%s: %s <port>:%s <input>:%d <err>:%d\n",
+                  __func__, err_str, task_p->transvr_p->swp_name, input_val, err_val);
+    }
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+_taskfunc_sfp_setup_hard_rs0(struct transvr_worker_s *task_p,
+                             int input_val) {
+
+    return __taskfunc_sfp_setup_hard_rs(task_p,
+                                        input_val,
+                                        task_p->transvr_p->ioexp_obj_p->get_hard_rs0,
+                                        task_p->transvr_p->ioexp_obj_p->set_hard_rs0);
+}
+
+
+int
+_taskfunc_sfp_setup_hard_rs1(struct transvr_worker_s *task_p,
+                             int input_val) {
+
+    return __taskfunc_sfp_setup_hard_rs(task_p,
+                                        input_val,
+                                        task_p->transvr_p->ioexp_obj_p->get_hard_rs1,
+                                        task_p->transvr_p->ioexp_obj_p->set_hard_rs1);
+}
+
+
+int
+_taskfunc_sfp_setup_rs0(struct transvr_worker_s *task_p,
+                        int input_val) {
+
+    int  bit_shift = 3;
+    int  old_val   = DEBUG_TRANSVR_INT_VAL;
+    int  err_val   = EVENT_TRANSVR_EXCEP_EXCEP;
+    char *err_str  = DEBUG_TRANSVR_STR_VAL;
+    char *func_str = "_taskfunc_sfp_setup_rs0";
+
+    err_val = _taskfunc_sfp_setup_hard_rs0(task_p,
+                                           input_val);
+    if (err_val < 0) {
+        err_str = "Setup hard_rs0 fail!";
+        goto err_private_taskfunc_sfp_setup_rs0_1;
+    }
+    old_val = err_val;
+    err_val = _taskfunc_sfp_setup_soft_rs(task_p,
+                                          input_val,
+                                          task_p->transvr_p->eeprom_map_p->addr_soft_rs0,
+                                          task_p->transvr_p->eeprom_map_p->page_soft_rs0,
+                                          task_p->transvr_p->eeprom_map_p->offset_soft_rs0,
+                                          bit_shift,
+                                          &(task_p->transvr_p->soft_rs0),
+                                          func_str);
+    if (err_val < 0) {
+        err_str = "Setup soft_rs0 fail!";
+        goto err_private_taskfunc_sfp_setup_rs0_1;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_private_taskfunc_sfp_setup_rs0_1:
+    if ((task_p->retry) == 0) {
+        SWPS_INFO("%s: %s <port>:%s <input>:%d <err>:%d\n",
+                  func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val);
+    }
+    _taskfunc_sfp_setup_hard_rs0(task_p, old_val);
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+_taskfunc_sfp_setup_rs1(struct transvr_worker_s *task_p,
+                        int input_val) {
+
+    int  bit_shift = 3;
+    int  old_val   = DEBUG_TRANSVR_INT_VAL;
+    int  err_val   = EVENT_TRANSVR_EXCEP_EXCEP;
+    char *err_str  = DEBUG_TRANSVR_STR_VAL;
+    char *func_str = "_taskfunc_sfp_setup_rs1";
+
+    err_val = _taskfunc_sfp_setup_hard_rs1(task_p,
+                                           input_val);
+    if (err_val < 0) {
+        err_str = "Setup hard_rs1 fail!";
+        goto err_private_taskfunc_sfp_setup_rs1_1;
+    }
+    old_val = err_val;
+    err_val = _taskfunc_sfp_setup_soft_rs(task_p,
+                                          input_val,
+                                          task_p->transvr_p->eeprom_map_p->addr_soft_rs1,
+                                          task_p->transvr_p->eeprom_map_p->page_soft_rs1,
+                                          task_p->transvr_p->eeprom_map_p->offset_soft_rs1,
+                                          bit_shift,
+                                          &(task_p->transvr_p->soft_rs1),
+                                          func_str);
+    if (err_val < 0) {
+        err_str = "Setup soft_rs1 fail!";
+        goto err_private_taskfunc_sfp_setup_rs1_1;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_private_taskfunc_sfp_setup_rs1_1:
+    if ((task_p->retry) == 0) {
+        SWPS_INFO("%s: %s <port>:%s <input>:%d <err>:%d\n",
+                  func_str, err_str, task_p->transvr_p->swp_name, input_val, err_val);
+    }
+    _taskfunc_sfp_setup_hard_rs1(task_p, old_val);
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+taskfunc_sfp_setup_SFF8431_case1(struct transvr_worker_s *task_p) {
+    /* SFF-8431 (8/4/2G Rx Rate_Select only) */
+    int update_val = 1;
+
+    return _taskfunc_sfp_setup_rs0(task_p, update_val);
+}
+
+
+
+int
+taskfunc_sfp_setup_SFF8431_case2(struct transvr_worker_s *task_p) {
+    /* SFF-8431 (8/4/2G Tx Rate_Select only) */
+    int update_val = 1;
+
+    return _taskfunc_sfp_setup_rs1(task_p, update_val);
+}
+
+
+int
+taskfunc_sfp_setup_SFF8431_case3(struct transvr_worker_s *task_p) {
+    /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */
+    int update_rs0 = 1;
+    int update_rs1 = 1;
+    int err_code   = DEBUG_TRANSVR_INT_VAL;
+
+    err_code = _taskfunc_sfp_setup_rs0(task_p, update_rs0);
+    if (err_code < 0) {
+        return err_code;
+    }
+    return _taskfunc_sfp_setup_rs1(task_p, update_rs1);
+}
+
+
+int
+taskfunc_sfp_handle_1g_rj45(struct transvr_worker_s *task_p) {
+
+    /* Not all of platform support 0x56 for transceiver
+     * external PHY, Support list as below:
+     * => 1. Magnolia-PVT (PS: EVT & DVT not ready)
+     */
+    int ext_phy_addr   = 0x56;
+    int ext_phy_page   = -1;
+    int ext_phy_offs   = 0x11;
+    int ext_phy_len    = 1;
+    int lstate_mask    = 0x04; /* 00000100 */
+    int show_err       = 0;
+    int fail_retry     = 5;
+    int fail_delay     = 1000; /* msec */
+    int err_code       = DEBUG_TRANSVR_INT_VAL;
+    uint8_t detect_val = DEBUG_TRANSVR_HEX_VAL;
+    char err_str[64]   = DEBUG_TRANSVR_STR_VAL;
+    int *tmp_p         = NULL;
+    char *func_name    = "taskfunc_sfp_handle_1g_rj45";
+
+    if (task_p->transvr_p->state != STATE_TRANSVR_CONNECTED) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    if ( (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000) &&
+         (task_p->transvr_p->info != TRANSVR_CLASS_BASE_T_1000_up) ) {
+        goto err_taskfunc_sfp_handle_1g_rj45_1;
+    }
+    err_code = _common_update_uint8_attr(task_p->transvr_p,
+                                         ext_phy_addr,
+                                         ext_phy_page,
+                                         ext_phy_offs,
+                                         ext_phy_len,
+                                         &detect_val,
+                                         func_name,
+                                         show_err);
+    if ( (err_code < 0) ||
+         (detect_val == DEBUG_TRANSVR_HEX_VAL) ) {
+        snprintf(err_str, sizeof(err_str), "Detect external link status fail");
+        goto err_taskfunc_sfp_handle_1g_rj45_2;
+    }
+    if ((detect_val & lstate_mask) == lstate_mask) {
+        goto ok_taskfunc_sfp_handle_1g_rj45_link_up;
+    }
+    goto ok_taskfunc_sfp_handle_1g_rj45_link_down;
+
+ok_taskfunc_sfp_handle_1g_rj45_link_up:
+    /* Filter out noise */
+    if (!(task_p->p_data)) {
+        tmp_p = kzalloc(sizeof(int), GFP_KERNEL);
+        if (!tmp_p) {
+            snprintf(err_str, sizeof(err_str), "kzalloc p_data fail");
+            goto err_taskfunc_sfp_handle_1g_rj45_2;
+        }
+        *tmp_p = TRANSVR_CLASS_BASE_T_1000_up;
+        task_p->p_data = tmp_p;
+        goto ok_taskfunc_sfp_handle_1g_rj45_done;
+    }
+    if ((*(int *)(task_p->p_data)) != TRANSVR_CLASS_BASE_T_1000_up) {
+        kfree(task_p->p_data);
+        task_p->p_data = NULL;
+        snprintf(err_str, sizeof(err_str), "Internal error");
+        goto err_taskfunc_sfp_handle_1g_rj45_2;
+    }
+    task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up;
+    kfree(task_p->p_data);
+    task_p->p_data = NULL;
+    goto ok_taskfunc_sfp_handle_1g_rj45_done;
+
+ok_taskfunc_sfp_handle_1g_rj45_link_down:
+    if (task_p->p_data) {
+        kfree(task_p->p_data);
+        task_p->p_data = NULL;
+    }
+    task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000;
+    goto ok_taskfunc_sfp_handle_1g_rj45_done;
+
+ok_taskfunc_sfp_handle_1g_rj45_done:
+    if (task_p->retry != VAL_TRANSVR_TASK_RETRY_FOREVER) {
+        transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER);
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_sfp_handle_1g_rj45_1:
+    snprintf(err_str, sizeof(err_str), "Detect transceiver:%d not Base-T, remove task.",
+            task_p->transvr_p->info);
+    SWPS_INFO("%s: %s <port>:%s\n", __func__, err_str, task_p->transvr_p->swp_name);
+    transvr_task_set_retry(task_p, 0);
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_sfp_handle_1g_rj45_2:
+    if (task_p->retry == VAL_TRANSVR_TASK_RETRY_FOREVER) {
+        transvr_task_set_retry(task_p, fail_retry);
+    }
+    if ((task_p->retry) == 0) {
+        /* Error case:
+         * => In this case, SWPS will stop external Link state monitor features
+         *    and keeps transvr_p->info on TRANSVR_CLASS_BASE_T_1000_up.
+         *    Upper layer will see it always Linkup that because of these type of
+         *    transceiver has external phy, BCM chip see it as Loopback transceiver.
+         */
+        SWPS_WARN("%s can not access external PHY of Base-T SFP transceiver\n",
+                task_p->transvr_p->swp_name);
+        task_p->transvr_p->info = TRANSVR_CLASS_BASE_T_1000_up;
+        return EVENT_TRANSVR_TASK_DONE;
+    } else {
+        transvr_task_set_delay(task_p, fail_delay);
+    }
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+_taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self,
+                               int setup_val) {
+
+    int curr_val   = DEBUG_TRANSVR_INT_VAL;
+    int err_val    = DEBUG_TRANSVR_INT_VAL;
+    char *err_msg  = DEBUG_TRANSVR_STR_VAL;
+
+    curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p,
+                                            self->ioexp_virt_offset);
+    if (curr_val < 0){
+        err_msg = "Get current value fail!";
+        goto err_private_taskfunc_qsfp_setup_power_mod_1;
+    }
+    if (curr_val == setup_val){
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    err_val = self->ioexp_obj_p->set_lpmod(self->ioexp_obj_p,
+                                           self->ioexp_virt_offset,
+                                           setup_val);
+    if (err_val < 0){
+        err_msg = "Setup power mode fail!";
+        goto err_private_taskfunc_qsfp_setup_power_mod_1;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_private_taskfunc_qsfp_setup_power_mod_1:
+    SWPS_INFO("%s: %s <err>:%d <curr>:%d <input>:%d\n",
+              __func__, err_msg, err_val, curr_val, setup_val);
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+taskfunc_qsfp_handle_tx_disable(struct transvr_worker_s *task_p) {
+
+    int i = 0;
+    int retry = 5;
+    int delay_ms = 100;
+
+    if (task_p->transvr_p->auto_tx_disable == VAL_TRANSVR_FUNCTION_DISABLE) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    if (!_qsfp_is_implement_tx_disable(task_p->transvr_p)) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    for (i=0; i<retry; i++) {
+        if (_qsfp_set_auto_tx_disable(task_p->transvr_p,
+                                      task_p->transvr_p->auto_tx_disable)
+                                      == EVENT_TRANSVR_TASK_DONE) {
+            goto ok_taskfunc_qsfp_handle_tx_disable;
+        }
+        mdelay(delay_ms);
+    }
+    SWPS_INFO("%s auto setup tx_disable:0x%02x fail.\n",
+              task_p->transvr_p->swp_name,
+              task_p->transvr_p->auto_tx_disable);
+    return EVENT_TRANSVR_INIT_FAIL;
+
+ok_taskfunc_qsfp_handle_tx_disable:
+    SWPS_INFO("%s auto setup tx_disable:0x%02x ok.\n",
+              task_p->transvr_p->swp_name,
+              task_p->transvr_p->auto_tx_disable);
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+taskfunc_qsfp_set_hpmod(struct transvr_worker_s *task_p) {
+
+    int err = DEBUG_TRANSVR_INT_VAL;
+    int HIGH_POWER_MODE = 0;
+
+    /* Handle power mode */
+    err = _taskfunc_qsfp_setup_power_mod(task_p->transvr_p,
+                                         HIGH_POWER_MODE);
+    if (err < 0) {
+        SWPS_INFO("%s: setup hpmod fail <err>:%d <port>:%s\n",
+                  __func__, err, task_p->transvr_p->swp_name);
+        return err;
+    }
+    /* Handle auto tx_disable
+     * [Note]
+     * => Because there are some transceiver have timing issues or
+     *    setup sequence issues, therefore we handle auto tx_disable
+     *    after handle power mode.
+     */
+    mdelay(100);
+    return taskfunc_qsfp_handle_tx_disable(task_p);
+}
+
+
+int
+taskfunc_qsfp_set_lpmod(struct transvr_worker_s *task_p) {
+
+    int LOW_POWER_MODE = 1;
+    return _taskfunc_qsfp_setup_power_mod(task_p->transvr_p,
+                                          LOW_POWER_MODE);
+}
+
+
+static int
+initfunc_sfp_handle_multi_rate_mode(struct transvr_obj_s *self) {
+
+    int task_retry = 3;
+    int err_code   = DEBUG_TRANSVR_INT_VAL;
+    char *err_str  = DEBUG_TRANSVR_STR_VAL;
+    char *func_str = "sfp_handle_multi_rate_mode";
+    struct transvr_worker_s *task_p = NULL;
+
+    switch (self->rate_id) {
+        case 0x00: /* Unspecified */
+        case 0x03: /* Unspecified */
+        case 0x05: /* Unspecified */
+        case 0x07: /* Unspecified */
+        case 0x09: /* Unspecified */
+        case 0x0B: /* Unspecified */
+        case 0x0D: /* Unspecified */
+        case 0x0F: /* Unspecified */
+            goto sfp_handle_multi_rate_mode_4_unspecified;
+
+        case 0x02: /* SFF-8431 (8/4/2G Rx Rate_Select only) */
+            task_p = transvr_task_creat(self,
+                                        taskfunc_sfp_setup_SFF8431_case1,
+                                        taskfunc_post_handle_task_state,
+                                        func_str);
+            goto sfp_handle_multi_rate_mode_4_sff8431;
+
+        case 0x04: /* SFF-8431 (8/4/2G Tx Rate_Select only) */
+            task_p = transvr_task_creat(self,
+                                        taskfunc_sfp_setup_SFF8431_case2,
+                                        taskfunc_post_handle_task_state,
+                                        func_str);
+            goto sfp_handle_multi_rate_mode_4_sff8431;
+
+        case 0x06: /* SFF-8431 (8/4/2G Independent Rx & Tx Rate_select) */
+            task_p = transvr_task_creat(self,
+                                        taskfunc_sfp_setup_SFF8431_case3,
+                                        taskfunc_post_handle_task_state,
+                                        func_str);
+            goto sfp_handle_multi_rate_mode_4_sff8431;
+
+        case 0x01: /* SFF-8079 (4/2/1G Rate_Select & AS0/AS1) */
+            err_str = "SFF-8079 (4/2/1G Rate_Select & AS0/AS1)";
+            goto sfp_handle_multi_rate_mode_4_not_support;
+
+        case 0x08: /* FC-PI-5 (16/8/4G Rx Rate_select only)
+                    * High=16G only, Low=8G/4G
+                    */
+            err_str = "FC-PI-5 (16/8/4G Rx Rate_select only)";
+            goto sfp_handle_multi_rate_mode_4_not_support;
+
+        case 0x0A: /* FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)
+                    * High=16G only, Low=8G/4G
+                    */
+            err_str = "FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select)";
+            goto sfp_handle_multi_rate_mode_4_not_support;
+
+        case 0x0C: /* FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)
+                    * High=32G only, Low = 16G/8G
+                    */
+            err_str = "FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)";
+            goto sfp_handle_multi_rate_mode_4_not_support;
+
+        case 0x0E: /* 10/8G Rx and Tx Rate_Select controlling the operation or
+                    * locking modes of the internal signal conditioner, retimer
+                    * or CDR, according to the logic table defined in Table 10-2,
+                    * High Bit Rate (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) =
+                    * 8.5 Gb/s. In this mode, the default value of bit 110.3 (Soft
+                    * Rate Select RS(0), Table 9-11) and of bit 118.3 (Soft Rate
+                    * Select RS(1), Table 10-1) is 1.
+                    */
+            err_str = "cable type: 0x0E";
+            goto sfp_handle_multi_rate_mode_4_not_support;
+
+        default:
+            err_str = "cable type: UNKNOW";
+            goto sfp_handle_multi_rate_mode_4_not_support;
+    }
+
+sfp_handle_multi_rate_mode_4_sff8431:
+    if (!task_p) {
+        err_str = "Create task fail!";
+        goto sfp_handle_multi_rate_mode_4_fail_1;
+    }
+    transvr_task_set_retry(task_p, task_retry);
+    return EVENT_TRANSVR_TASK_WAIT;
+
+sfp_handle_multi_rate_mode_4_unspecified:
+    return EVENT_TRANSVR_TASK_DONE;
+
+sfp_handle_multi_rate_mode_4_not_support:
+    SWPS_INFO("%s: Does not support %s <port>:%s <type>:0x%02x\n",
+            func_str, err_str, self->swp_name, self->rate_id);
+    return EVENT_TRANSVR_TASK_DONE;
+
+sfp_handle_multi_rate_mode_4_fail_1:
+    SWPS_INFO("%s: %s <port>:%s <type>:0x%02x, <err>:%d\n",
+              func_str, err_str, self->swp_name, self->rate_id, err_code);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+static int
+initfunc_sfp_handle_1g_rj45(struct transvr_obj_s *self) {
+
+    struct transvr_worker_s *task_p = NULL;
+    int detect_cls   = DEBUG_TRANSVR_INT_VAL;
+    char err_str[64] = DEBUG_TRANSVR_STR_VAL;
+    char *func_str   = "initfunc_sfp_handle_1g_rj45";
+
+
+    if (self->info == TRANSVR_CLASS_BASE_T_1000) {
+        task_p = transvr_task_creat(self,
+                                    taskfunc_sfp_handle_1g_rj45,
+                                    taskfunc_post_do_nothing,
+                                    func_str);
+        if (!task_p) {
+            snprintf(err_str, sizeof(err_str), "Create task fail");
+            goto err_initfunc_sfp_handle_1g_rj45;
+        }
+        transvr_task_set_retry(task_p, VAL_TRANSVR_TASK_RETRY_FOREVER);
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_initfunc_sfp_handle_1g_rj45:
+    SWPS_INFO("%s: %s <port>:%s <type>:%d\n",
+              __func__, err_str, self->swp_name, detect_cls);
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+static int
+initfunc_qsfp_handle_power_mode(struct transvr_obj_s *self) {
+
+    int err_code      = EVENT_TRANSVR_EXCEP_INIT;
+    int power_class   = DEBUG_TRANSVR_INT_VAL;
+    int hpmod_retry   = 3;
+    int lpower_config = 1;
+    char err_msg[64]  = DEBUG_TRANSVR_STR_VAL;
+    unsigned long hpmod_delay = 500; /* msec */
+    struct transvr_worker_s *task_p = NULL;
+
+    /* Handle power mode for IOEXP */
+    power_class = __qsfp_get_power_cls(self, 0);
+    switch (power_class) {
+        case 1: /* Case: Low power mode (Class = 1) */
+            err_code = _taskfunc_qsfp_setup_power_mod(self, lpower_config);
+            if (err_code < 0){
+                snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail <ERR>:%d", err_code);
+                goto err_initfunc_qsfp_handle_power_mode;
+            }
+            return EVENT_TRANSVR_TASK_DONE;
+
+        case 2: /* Case: High power mode (Class > 1) */
+        case 3:
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+            task_p = transvr_task_creat(self,
+                                        taskfunc_qsfp_set_hpmod,
+                                        taskfunc_post_handle_task_state,
+                                        "transvr_init_qsfp");
+            if (!task_p) {
+                snprintf(err_msg, sizeof(err_msg), "Setup lpmod fail <ERR>:%d", err_code);
+                goto err_initfunc_qsfp_handle_power_mode;
+            }
+            transvr_task_set_retry(task_p, hpmod_retry);
+            transvr_task_set_delay(task_p, hpmod_delay);
+            return EVENT_TRANSVR_TASK_WAIT;
+
+        default:
+            break;
+    }
+    snprintf(err_msg, sizeof(err_msg), "Exception case");
+    goto err_initfunc_qsfp_handle_power_mode;
+
+err_initfunc_qsfp_handle_power_mode:
+    SWPS_INFO("%s: %s <port>:%s \n", __func__, err_msg, self->swp_name);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+int
+initfunc_qsfp28_handle_cdr(struct transvr_obj_s *self) {
+
+    uint8_t DEFAULT_VAL_CDR = 0xff;
+    int CDR_FUNC_EXISTED    = 0x3;
+    int show_err   = 1;
+    int err_val    = EVENT_TRANSVR_TASK_FAIL;
+    char *err_msg  = DEBUG_TRANSVR_STR_VAL;
+    char *func_str = "initfunc_qsfp28_handle_cdr";
+
+    err_val = __qsfp_get_cdr_present(self, 0);
+    if ( (err_val < 0) ||
+         (err_val == DEBUG_TRANSVR_HEX_VAL) ) {
+        err_msg = "detect cdr_present fail!";
+        goto err_taskfunc_qsfp_handle_cdr_1;
+    }
+    if (err_val == CDR_FUNC_EXISTED) {
+        err_val = _common_set_uint8_attr(self,
+                                         self->eeprom_map_p->addr_cdr,
+                                         self->eeprom_map_p->addr_cdr,
+                                         self->eeprom_map_p->offset_cdr,
+                                         DEFAULT_VAL_CDR,
+                                         &(self->cdr),
+                                         func_str,
+                                         show_err);
+        if (err_val < 0) {
+            err_msg = "set CDR fail!";
+            goto err_taskfunc_qsfp_handle_cdr_1;
+        }
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_taskfunc_qsfp_handle_cdr_1:
+    SWPS_INFO("%s: %s <err>:%d <port>:%s\n",
+              func_str, err_msg, err_val, self->swp_name);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+/* ========== Object functions for Final State Machine ==========
+ */
+int
+is_plugged(struct transvr_obj_s *self){
+
+    int  limit    = 63;
+    int  present  = DEBUG_TRANSVR_INT_VAL;
+    char emsg[64] = DEBUG_TRANSVR_STR_VAL;
+    struct ioexp_obj_s *ioexp_p = self->ioexp_obj_p;
+
+    if (!ioexp_p) {
+        snprintf(emsg, limit, "ioexp_p is null!");
+        goto err_is_plugged_1;
+    }
+    present = ioexp_p->get_present(ioexp_p, self->ioexp_virt_offset);
+    switch (present){
+        case 0:
+            return 1;
+        case 1:
+            return 0;
+        case ERR_IOEXP_UNINIT:
+            snprintf(emsg, limit, "ioexp_p not ready!");
+            goto err_is_plugged_1;
+        default:
+            if (ioexp_p->state == STATE_IOEXP_INIT){
+                snprintf(emsg, limit, "ioexp_p not ready!");
+                goto err_is_plugged_1;
+            }
+            break;
+    }
+    SWPS_INFO("%s: Exception case! <pres>:%d <istate>:%d\n",
+              __func__, present, ioexp_p->state);
+    return 0;
+
+err_is_plugged_1:
+    SWPS_DEBUG("%s: %s\n", __func__, emsg);
+    return 0;
+}
+
+
+static int
+detect_transvr_type(struct transvr_obj_s* self){
+
+    int type = TRANSVR_TYPE_ERROR;
+
+    self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS;
+    type = i2c_smbus_read_byte_data(self->i2c_client_p,
+                                    VAL_TRANSVR_COMID_OFFSET);
+
+    /* Case: 1. Wait transceiver I2C module.
+     *       2. Transceiver I2C module failure.
+     * Note: 1. SFF allow maximum transceiver initial time is 2 second. So, there
+     *          are exist some case that we need to wait transceiver.
+     *          For these case, we keeps status on "TRANSVR_TYPE_UNPLUGGED", than
+     *          state machine will keep trace with it.
+     *       2. There exist some I2C failure case we need to handle. Such as user
+     *          insert the failure transceiver, or any reason cause it abnormal.
+     */
+    if (type < 0){
+        switch (type) {
+            case -EIO:
+                SWPS_DEBUG("%s: %s smbus return:-5 (I/O error)\n",
+                        __func__, self->swp_name);
+                return TRANSVR_TYPE_UNPLUGGED;
+            case -ENXIO:
+                SWPS_DEBUG("%s: %s smbus return:-6 (No such device or address)\n",
+                        __func__, self->swp_name);
+                return TRANSVR_TYPE_UNPLUGGED;
+            default:
+                break;
+        }
+        SWPS_INFO("%s: %s unexpected smbus return:%d \n",
+                __func__, self->swp_name, type);
+        return TRANSVR_TYPE_ERROR;
+    }    
+    /* Identify valid transceiver type */
+    switch (type){
+        case TRANSVR_TYPE_SFP:
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+        case TRANSVR_TYPE_QSFP_28:
+            break;
+        case TRANSVR_TYPE_UNKNOW_1:
+        case TRANSVR_TYPE_UNKNOW_2:
+            type = TRANSVR_TYPE_UNKNOW_2;
+            break;
+        default:
+            SWPS_DEBUG("%s: unknow type:0x%02x \n", __func__, type);
+            type = TRANSVR_TYPE_ERROR;
+            break;
+    }
+    return type;
+}
+
+
+static int
+detect_transvr_state(struct transvr_obj_s *self,
+                     int result[2]){
+    /* [return]                  [result-0]                  [result-1]
+     *  0                        STATE_TRANSVR_CONNECTED     TRANSVR_TYPE_FAKE
+     *  0                        STATE_TRANSVR_DISCONNECTED  TRANSVR_TYPE_UNPLUGGED
+     *  0                        STATE_TRANSVR_ISOLATED      TRANSVR_TYPE_ERROR
+     *  0                        STATE_TRANSVR_INIT          <NEW_TYPE>/<OLD_TYPE>
+     *  0                        STATE_TRANSVR_SWAPPED       <NEW_TYPE>
+     *  0                        STATE_TRANSVR_CONNECTED     <OLD_TYPE>
+     *  ERR_TRNASVR_BE_ISOLATED  STATE_TRANSVR_ISOLATED      TRANSVR_TYPE_ERROR  <Isolated>
+     *  ERR_TRANSVR_I2C_CRASH    STATE_TRANSVR_UNEXCEPTED    TRANSVR_TYPE_ERROR  <New event>
+     *  ERR_TRANSVR_UNEXCPT      STATE_TRANSVR_UNEXCEPTED    TRANSVR_TYPE_UNKNOW_1/2
+     */
+    result[0] = STATE_TRANSVR_UNEXCEPTED;  /* For return state */
+    result[1] = TRANSVR_TYPE_ERROR;        /* For return type  */
+
+    /* Case1: Fake type */
+    if (self->type == TRANSVR_TYPE_FAKE){
+        result[0] = STATE_TRANSVR_CONNECTED;
+        result[1] = TRANSVR_TYPE_FAKE;
+        return 0;
+    }
+    /* Case2: Transceiver unplugged */
+    if (!is_plugged(self)){
+        result[0] = STATE_TRANSVR_DISCONNECTED;
+        result[1] = TRANSVR_TYPE_UNPLUGGED;
+        return 0;
+    }
+    /* Case3: Transceiver be isolated */
+    if (self->state == STATE_TRANSVR_ISOLATED){
+        result[0] = STATE_TRANSVR_ISOLATED;
+        result[1] = TRANSVR_TYPE_ERROR;
+        return ERR_TRNASVR_BE_ISOLATED;
+    }
+    /* Case4: Transceiver plugged */
+    result[1] = detect_transvr_type(self);
+    /* Case4.1: I2C topology crash
+     * Note   : There are some I2C issues cause by transceiver/cables.
+     *          We need to check topology status when user insert it.
+     *          But in this step, we can't not ensure this is the issues
+     *          port. So, it return the ERR_TRANSVR_I2C_CRASH, then upper
+     *          layer will diagnostic I2C topology.
+     */
+    if (check_channel_tier_1() < 0) {
+        SWPS_INFO("%s: %s detect I2C crash <obj-state>:%d\n",
+                __func__, self->swp_name, self->state);
+        result[0] = STATE_TRANSVR_UNEXCEPTED;
+        result[1] = TRANSVR_TYPE_ERROR;
+        return ERR_TRANSVR_I2C_CRASH;
+    }
+    /* Case4.2: System initial not ready,
+     * Note   : Sometime i2c channel or transceiver EEPROM will delay that will
+     *          cause system in inconsistent state between EEPROM and IOEXP.
+     *          In this case, SWP transceiver object keep state at LINK_DOWN
+     *          to wait system ready.
+     *          By the way, State Machine will handle these case.
+     */
+    if (result[1] == TRANSVR_TYPE_UNPLUGGED){
+        result[0] = STATE_TRANSVR_DISCONNECTED;
+        return 0;
+    }
+    /* Case4.3: Error transceiver type */
+    if (result[1] == TRANSVR_TYPE_ERROR){
+        result[0] = STATE_TRANSVR_ISOLATED;
+        SWPS_INFO("%s: %s detect error type\n", __func__, self->swp_name);
+        alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard!");
+        return ERR_TRNASVR_BE_ISOLATED;
+    }
+    /* Case3.3: Unknow transceiver type */
+    if ((result[1] == TRANSVR_TYPE_UNKNOW_1) ||
+        (result[1] == TRANSVR_TYPE_UNKNOW_2) ){
+        result[0] = STATE_TRANSVR_UNEXCEPTED;
+        return ERR_TRANSVR_UNEXCPT;
+    }
+    /* Case3.4: During initial process */
+    if (self->state == STATE_TRANSVR_INIT){
+        result[0] = STATE_TRANSVR_INIT;
+        return 0;
+    }
+    /* Case3.5: Transceiver be swapped */
+    if (self->type != result[1]){
+        result[0] = STATE_TRANSVR_SWAPPED;
+        return 0;
+    }
+    /* Case3.6: Link up state */
+    result[0] = STATE_TRANSVR_CONNECTED;
+    return 0;
+}
+
+
+int
+_sfp_detect_class_by_extend_comp(struct transvr_obj_s* self) {
+    /* Reference: SFF-8024 (v3.8)
+     */
+    int detect_val = _sfp_get_comp_extended(self);
+
+    switch(detect_val) {
+        case 0x00: /* Unspecified */
+            return TRANSVR_CLASS_UNSPECIFIED;
+
+        case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */
+        case 0x18: /* 100G AOC or 25GAUI C2M AOC. */
+            return TRANSVR_CLASS_OPTICAL_25G_AOC;
+
+        case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */
+            return TRANSVR_CLASS_OPTICAL_25G_SR;
+
+        case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */
+            return TRANSVR_CLASS_OPTICAL_25G_LR;
+
+        case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */
+            return TRANSVR_CLASS_OPTICAL_25G_ER;
+
+        case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */
+        case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */
+        case 0x0c: /* 25GBASE-CR CA-S */
+        case 0x0d: /* 25GBASE-CR CA-N */
+        case 0x19: /* 100G ACC or 25GAUI C2M ACC. */
+            return TRANSVR_CLASS_COPPER_L1_25G;
+
+        default:
+            break;
+    }
+    SWPS_INFO("%s: Unexcept value:0x%02x\n <port>:%s",
+              __func__, detect_val, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+_sfp_detect_class_by_10_ethernet(struct transvr_obj_s* self) {
+    /* Reference: SFF-8472 (v12.2)
+     */
+    int detect_val = DEBUG_TRANSVR_INT_VAL;
+
+    detect_val = _sfp_get_comp_10g_eth_comp(self);
+    /* Case: Unspecified */
+    if (detect_val == 0x00) {
+        return TRANSVR_CLASS_UNSPECIFIED;
+    }
+    /* Case: 10G Optical (x1) */
+    if ((detect_val & 0x10) == 0x10) {    /* 00010000 : 10GBASE-SR  */
+        return TRANSVR_CLASS_OPTICAL_10G_S_SR;
+    }
+    if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR  */
+         ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */
+        return TRANSVR_CLASS_OPTICAL_10G_S_LR;
+    }
+    if ((detect_val & 0x80) == 0x80) {    /* 10000000 : 10GBASE-ER  */
+        return TRANSVR_CLASS_OPTICAL_10G_S_ER;
+    }
+    /* Case: ERROR */
+    SWPS_INFO("%s: Unexcept value:0x%02x\n <port>:%s",
+              __func__, detect_val, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+_sfp_detect_if_sp_by_br(struct transvr_obj_s* self) {
+
+    int lower_bound_1g  = 0x0b;
+    int upper_bound_1g  = 0x1A;
+    int lower_bound_10g = 0x60;
+    int upper_bound_10g = 0x75;
+    int lower_bound_25g = 0xf0;
+    int upper_bound_25g = 0xff;
+    int notmal_br = DEBUG_TRANSVR_INT_VAL;
+
+    notmal_br = (int)(self->br); /* updated by update_all() */
+    /* Check 25G */
+    if ((notmal_br >= lower_bound_25g) &&
+        (notmal_br <= upper_bound_25g) ) {
+        return TRANSVR_CLASS_25G;
+    }
+    /* Check 10G */
+    if ((notmal_br >= lower_bound_10g) &&
+        (notmal_br <= upper_bound_10g) ) {
+        return TRANSVR_CLASS_10G;
+    }
+    /* Check 1G */
+    if ((notmal_br >= lower_bound_1g) &&
+        (notmal_br <= upper_bound_1g) ) {
+        return TRANSVR_CLASS_1G;
+    }
+    return TRANSVR_CLASS_UNSPECIFIED;
+}
+
+
+int
+_sfp_detect_class_by_1g_ethernet(struct transvr_obj_s* self) {
+    /* Reference: SFF-8472 (v12.2)
+     */
+    int detect_val   = DEBUG_TRANSVR_INT_VAL;
+    int speed_br     = DEBUG_TRANSVR_INT_VAL;
+    int speed_tmp    = DEBUG_TRANSVR_INT_VAL;
+    char err_str[64] = DEBUG_TRANSVR_STR_VAL;
+
+    speed_br   = _sfp_detect_if_sp_by_br(self);
+    detect_val = _sfp_get_comp_1g_eth_comp(self);
+
+    if (detect_val < 0) {
+        snprintf(err_str, sizeof(err_str), "Detect abnormal value:%d", detect_val);
+        goto err_p_sfp_detect_class_by_1g_ethernet;
+    }
+    /* Case: Unspecified */
+    if (detect_val == 0x00) {
+        return TRANSVR_CLASS_UNSPECIFIED;
+    }
+    /* Case: 1G (x1) */
+    if ((detect_val & 0x01) == 0x01) {    /* 00000001 : 1000BASE-SX    */
+        speed_tmp = TRANSVR_CLASS_OPTICAL_1G_SX;
+        goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g;
+    }
+    if ((detect_val & 0x02) == 0x02) {    /* 00000010 : 1000BASE-LX *3 */
+        speed_tmp = TRANSVR_CLASS_OPTICAL_1G_LX;
+        goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g;
+    }
+    if ((detect_val & 0x04) == 0x04) {    /* 00000100 : 1000BASE-CX    */
+        speed_tmp = TRANSVR_CLASS_COPPER_L1_1G;
+        goto ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g;
+    }
+    /* Case: 1000 Base-T (x1) */
+    if ((detect_val & 0x08) == 0x08) {    /* 00001000 : 1000BASE-T     */
+        return TRANSVR_CLASS_BASE_T_1000;
+    }
+    /* Case: 100 Base */
+    if ( ((detect_val & 0x10) == 0x10) || /* 00010000 : 100BASE-LX/LX10  */
+         ((detect_val & 0x20) == 0x20) || /* 00100000 : 100BASE-FX  */
+         ((detect_val & 0x40) == 0x40) || /* 01000000 : BASE-BX10 *3 */
+         ((detect_val & 0x80) == 0x80) ){ /* 10000000 : BASE-PX *3  */
+        return TRANSVR_CLASS_OPTICAL_100;
+    }
+    /* Case: ERROR */
+    snprintf(err_str, sizeof(err_str), "Case:ERROR, value:%d", detect_val);
+    goto err_p_sfp_detect_class_by_1g_ethernet;
+
+ok_sfp_detect_class_by_1g_ethernet_4_check_br_10g:
+    switch (speed_br) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+        case TRANSVR_CLASS_1G:
+            return speed_tmp;
+        case TRANSVR_CLASS_10G:
+            goto ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G;
+    }
+
+ok_sfp_detect_class_by_1g_ethernet_4_transfer_10G:
+    switch (speed_tmp) {
+        case TRANSVR_CLASS_OPTICAL_1G_SX:
+            return TRANSVR_CLASS_OPTICAL_10G_S_SR;
+        case TRANSVR_CLASS_OPTICAL_1G_LX:
+            return TRANSVR_CLASS_OPTICAL_10G_S_LR;
+        case TRANSVR_CLASS_COPPER_L1_1G:
+            return TRANSVR_CLASS_COPPER_L1_10G;
+        default:
+            break;
+    }
+    snprintf(err_str, sizeof(err_str), "transfer_1to10 fail, speed:%d", speed_tmp);
+    goto err_p_sfp_detect_class_by_1g_ethernet;
+
+err_p_sfp_detect_class_by_1g_ethernet:
+    SWPS_INFO("%s: %s <port>:%s", __func__, err_str, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+_sfp_detect_class_by_feature(struct transvr_obj_s* self) {
+    /* Reference: SFF-8024 (v3.8)
+     */
+    int is_active    = 0;
+    int conn_val     = DEBUG_TRANSVR_INT_VAL;
+    int check_val    = DEBUG_TRANSVR_INT_VAL;
+    int wave_len     = DEBUG_TRANSVR_INT_VAL;
+    int speed_val    = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    speed_val = _sfp_detect_if_sp_by_br(self);
+    conn_val  = _sfp_get_connector_type(self);
+
+    switch(conn_val) {
+        case 0x00: /* Unspecified */
+            goto ok_sfp_detect_class_by_feature_4_check_active_passive;
+        case 0x07: /* LC (Lucent Connector) */
+        case 0x0b: /* Optical Pigtail */
+        case 0x0c: /* MPO 1x12 */
+        case 0x0d: /* MPO 2x16 */
+            /*
+             * ToDo: Need verify Optical Pigtail
+             */
+            goto ok_sfp_detect_class_by_feature_4_optiocal;
+        case 0x21: /* Copper pigtail */
+            /*
+             * ToDo: Need check ACC use case
+             */
+            goto ok_sfp_detect_class_by_feature_4_check_active_passive;
+        case 0x23: /* No separable connector */
+            /*
+             * ToDo: Standard not clear, not all transceiver vendor
+             *       have the same defined
+             */
+            goto ok_sfp_detect_class_by_feature_4_check_active_passive;
+        default:
+            break;
+    }
+    goto ok_sfp_detect_class_by_feature_4_unknow;
+
+ok_sfp_detect_class_by_feature_4_check_active_passive:
+    check_val = _sfp_get_cable_tech(self);
+    switch(check_val) {
+        case 0x00: /* Unspecified */
+            goto ok_sfp_detect_class_by_feature_4_unknow;
+        case 0x04: /* Passive */
+            goto ok_sfp_detect_class_by_feature_4_copper;
+        case 0x08: /* Active  */
+            is_active = 1;
+            goto ok_sfp_detect_class_by_feature_4_aoc;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "_sfp_get_cable_tech return Non define value:%d",
+                     check_val);
+            break;
+    }
+    goto err_sfp_detect_class_by_feature_1;
+
+ok_sfp_detect_class_by_feature_4_optiocal:
+    wave_len  = _common_count_wavelength(self,
+                                         self->wavelength[0],
+                                         self->wavelength[1]);
+    switch(speed_val) {
+        case TRANSVR_CLASS_25G:
+            switch (wave_len) {
+                case VAL_OPTICAL_WAVELENGTH_SR:
+                    return TRANSVR_CLASS_OPTICAL_25G_SR;
+                case VAL_OPTICAL_WAVELENGTH_LR:
+                    return TRANSVR_CLASS_OPTICAL_25G_LR;
+                case VAL_OPTICAL_WAVELENGTH_ER:
+                    return TRANSVR_CLASS_OPTICAL_25G_ER;
+                default:
+                    break;
+            }
+            return TRANSVR_CLASS_OPTICAL_25G;
+
+        case TRANSVR_CLASS_10G:
+            switch (wave_len) {
+                case VAL_OPTICAL_WAVELENGTH_SR:
+                    return TRANSVR_CLASS_OPTICAL_10G_S_SR;
+                case VAL_OPTICAL_WAVELENGTH_LR:
+                    return TRANSVR_CLASS_OPTICAL_10G_S_LR;
+                case VAL_OPTICAL_WAVELENGTH_ER:
+                    return TRANSVR_CLASS_OPTICAL_10G_S_ER;
+                default:
+                    break;
+            }
+            return TRANSVR_CLASS_OPTICAL_10G;
+
+        case TRANSVR_CLASS_1G:
+            switch (wave_len) {
+                case VAL_OPTICAL_WAVELENGTH_SR:
+                    return TRANSVR_CLASS_OPTICAL_1G_SX;
+                case VAL_OPTICAL_WAVELENGTH_LR:
+                    return TRANSVR_CLASS_OPTICAL_1G_LX;
+                case VAL_OPTICAL_WAVELENGTH_ER:
+                    return TRANSVR_CLASS_OPTICAL_1G_EX;
+                default:
+                    break;
+            }
+            return TRANSVR_CLASS_OPTICAL_1G;
+
+        default:
+            return TRANSVR_CLASS_OPTICAL;
+    }
+
+ok_sfp_detect_class_by_feature_4_aoc:
+    switch(speed_val) {
+        case TRANSVR_CLASS_25G:
+            return TRANSVR_CLASS_OPTICAL_25G_AOC;
+        case TRANSVR_CLASS_10G:
+            return TRANSVR_CLASS_OPTICAL_10G_S_AOC;
+        case TRANSVR_CLASS_1G:
+            return TRANSVR_CLASS_OPTICAL_1G_AOC;
+        default:
+            break;
+    }
+    goto ok_sfp_detect_class_by_feature_4_unknow;
+
+ok_sfp_detect_class_by_feature_4_copper:
+    switch(speed_val) {
+        case TRANSVR_CLASS_25G:
+            return TRANSVR_CLASS_COPPER_L1_25G;
+        case TRANSVR_CLASS_10G:
+            return TRANSVR_CLASS_COPPER_L1_10G;
+        case TRANSVR_CLASS_1G:
+            return TRANSVR_CLASS_COPPER_L1_1G;
+        default:
+            return TRANSVR_CLASS_COPPER;
+    }
+
+ok_sfp_detect_class_by_feature_4_unknow:
+    return TRANSVR_CLASS_UNSPECIFIED;
+
+err_sfp_detect_class_by_feature_1:
+    SWPS_INFO("%s: %s\n <port>:%s", __func__, err_msg, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+sft_detect_transvr_class(struct transvr_obj_s* self) {
+
+    int detect_val   = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    /* Check Extended Compliance */
+    detect_val = _sfp_detect_class_by_extend_comp(self);
+    switch(detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_OPTICAL_25G_AOC:
+        case TRANSVR_CLASS_OPTICAL_25G_SR:
+        case TRANSVR_CLASS_OPTICAL_25G_LR:
+        case TRANSVR_CLASS_OPTICAL_25G_ER:
+        case TRANSVR_CLASS_COPPER_L1_25G:
+            return detect_val;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined extend_comp:%d",
+                     detect_val);
+            goto err_sft_detect_transceiver_class_1;
+    }
+    /* Check 10G Compliance */
+    detect_val = _sfp_detect_class_by_10_ethernet(self);
+    switch(detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_OPTICAL_10G_S_SR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_LR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_ER:
+            return detect_val;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                    "Detect undefined 10G_eth:%d",
+                     detect_val);
+            goto err_sft_detect_transceiver_class_1;
+    }
+    /* Check 1G Compliance */
+    detect_val = _sfp_detect_class_by_1g_ethernet(self);
+    switch(detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_OPTICAL_1G_SX:
+        case TRANSVR_CLASS_OPTICAL_1G_LX:
+        case TRANSVR_CLASS_COPPER_L1_1G:
+        case TRANSVR_CLASS_BASE_T_1000:
+        case TRANSVR_CLASS_OPTICAL_100:
+            /*
+             * ToDo: Need Check 0.1G
+             */
+        case TRANSVR_CLASS_OPTICAL_10G_S_SR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_LR:
+        case TRANSVR_CLASS_COPPER_L1_10G:
+            /* Transfer speed case
+             * => Example: Raycom 10G DAC
+             */
+            return detect_val;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined 1G_eth:%d",
+                     detect_val);
+            goto err_sft_detect_transceiver_class_1;
+    }
+    /* Check by connector, br, wavelength */
+    detect_val = _sfp_detect_class_by_feature(self);
+    switch(detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_OPTICAL:
+        case TRANSVR_CLASS_OPTICAL_1G:
+        case TRANSVR_CLASS_OPTICAL_1G_SX:
+        case TRANSVR_CLASS_OPTICAL_1G_LX:
+        case TRANSVR_CLASS_OPTICAL_1G_EX:
+        case TRANSVR_CLASS_OPTICAL_1G_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G:
+        case TRANSVR_CLASS_OPTICAL_10G_S_SR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_LR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_ER:
+        case TRANSVR_CLASS_OPTICAL_10G_S_AOC:
+        case TRANSVR_CLASS_OPTICAL_25G:
+        case TRANSVR_CLASS_OPTICAL_25G_SR:
+        case TRANSVR_CLASS_OPTICAL_25G_LR:
+        case TRANSVR_CLASS_OPTICAL_25G_ER:
+        case TRANSVR_CLASS_OPTICAL_25G_AOC:
+        case TRANSVR_CLASS_COPPER:
+        case TRANSVR_CLASS_COPPER_L1_1G:
+        case TRANSVR_CLASS_COPPER_L1_10G:
+        case TRANSVR_CLASS_COPPER_L1_25G:
+            return detect_val;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined get_connector:%d",
+                     detect_val);
+            goto err_sft_detect_transceiver_class_1;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg), "Can not identify!");
+    goto err_sft_detect_transceiver_class_1;
+
+err_sft_detect_transceiver_class_1:
+    SWPS_INFO("%s: %s <port>:%s\n", __func__,  err_msg, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+_sfp_set_trident2_if_type(struct transvr_obj_s* self,
+                          int transvr_cls,
+                          char *result){
+
+    int lmax = 8;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    switch(transvr_cls) {
+        case TRANSVR_CLASS_ERROR:
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        /* 25G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_25G_AOC:
+        case TRANSVR_CLASS_OPTICAL_25G_SR:
+        case TRANSVR_CLASS_OPTICAL_25G_LR:
+        case TRANSVR_CLASS_OPTICAL_25G_ER:
+        case TRANSVR_CLASS_OPTICAL_25G:
+            return snprintf(result, lmax, TRANSVR_IF_SFI);
+        /* 25G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_25G:
+            return snprintf(result, lmax, TRANSVR_IF_SFI);
+        /* 10G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_10G_S_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G_S_SR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_LR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_ER:
+        case TRANSVR_CLASS_OPTICAL_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SFI);
+        /* 10G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SFI);
+        /* 1G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_1G_AOC:
+        case TRANSVR_CLASS_OPTICAL_1G_SX:
+        case TRANSVR_CLASS_OPTICAL_1G_LX:
+        case TRANSVR_CLASS_OPTICAL_1G_EX:
+        case TRANSVR_CLASS_OPTICAL_1G:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        /* 1G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_1G:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        /* 1G BASE_T */
+        case TRANSVR_CLASS_BASE_T_1000:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        /* 100 Base */
+        case TRANSVR_CLASS_OPTICAL_100:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined value:%d",
+                     transvr_cls);
+            goto err_sfp_set_trident2_if_type_1;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg), "Can not identify!");
+    goto err_sfp_set_trident2_if_type_1;
+
+err_sfp_set_trident2_if_type_1:
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    SWPS_INFO("%s: %s <port>:%s\n", __func__, err_msg, self->swp_name);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_sfp_set_tomahawk_if_type(struct transvr_obj_s* self,
+                          int transvr_cls,
+                          char *result) {
+
+    int lmax = 8;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    switch(transvr_cls) {
+        case TRANSVR_CLASS_ERROR:
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        /* 25G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_25G_AOC:
+        case TRANSVR_CLASS_OPTICAL_25G_SR:
+        case TRANSVR_CLASS_OPTICAL_25G_LR:
+        case TRANSVR_CLASS_OPTICAL_25G_ER:
+        case TRANSVR_CLASS_OPTICAL_25G:
+            return snprintf(result, lmax, TRANSVR_IF_SR);
+        /* 25G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_25G:
+            return snprintf(result, lmax, TRANSVR_IF_KR);
+        /* 10G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_10G_S_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G_S_SR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_LR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_ER:
+        case TRANSVR_CLASS_OPTICAL_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SFI);
+        /* 10G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SFI);
+        /* 1G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_1G_AOC:
+        case TRANSVR_CLASS_OPTICAL_1G_SX:
+        case TRANSVR_CLASS_OPTICAL_1G_LX:
+        case TRANSVR_CLASS_OPTICAL_1G_EX:
+        case TRANSVR_CLASS_OPTICAL_1G:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        /* 1G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_1G:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        /* 1G BASE_T */
+        case TRANSVR_CLASS_BASE_T_1000:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        /* 100 Base */
+        case TRANSVR_CLASS_OPTICAL_100:
+            return snprintf(result, lmax, TRANSVR_IF_IF_GMII);
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined value:%d",
+                     transvr_cls);
+            goto err_sfp_set_tomahawk_if_type_1;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg), "Can not identify!");
+    goto err_sfp_set_tomahawk_if_type_1;
+
+err_sfp_set_tomahawk_if_type_1:
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    SWPS_INFO("%s: %s\n <port>:%s", __func__, err_msg, self->swp_name);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_sfp_set_bf_tofino_if_type(struct transvr_obj_s* self,
+                           int transvr_cls,
+                           char *result) {
+    /* (TBD)
+     *  Due to BF looks like doesn't have interface type.
+     *  We bypass it currently.
+     */
+    int lmax = 8;    
+    return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+}
+
+
+int
+_sfp_detect_if_type(struct transvr_obj_s* self,
+                    char *result){
+
+    int lmax = 8;
+    int detect_cls = DEBUG_TRANSVR_INT_VAL;
+
+    detect_cls = sft_detect_transvr_class(self);
+    switch (self->chipset_type) {
+        case BCM_CHIP_TYPE_TRIDENT_2:
+            return _sfp_set_trident2_if_type(self, detect_cls, result);
+        
+        case BCM_CHIP_TYPE_TRIDENT_3:
+        case BCM_CHIP_TYPE_TOMAHAWK:
+            return _sfp_set_tomahawk_if_type(self, detect_cls, result);
+
+        case BF_CHIP_TYPE_TOFINO:
+            return _sfp_set_bf_tofino_if_type(self, detect_cls, result);
+            
+        default:
+            SWPS_INFO("%s: non-defined chipset_type:%d <port>:%s\n",
+                      __func__, self->chipset_type, self->swp_name);
+            break;
+    }
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+sfp_get_if_type(struct transvr_obj_s *self,
+                char *buf_p){
+
+    int lmax = 16;
+    char tmp_result[16] = DEBUG_TRANSVR_STR_VAL;
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return snprintf(buf_p, lmax, "%d\n", self->state);
+    }
+    if (_sfp_detect_if_type(self, tmp_result) < 0) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL);
+    }
+    return snprintf(buf_p, lmax, "%s\n", tmp_result);
+}
+
+
+int
+_sfp_detect_if_speed(struct transvr_obj_s* self,
+                     char *result){
+
+    int lmax = 16;
+    int detect_val   = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    detect_val = sft_detect_transvr_class(self);
+    switch(detect_val) {
+        case TRANSVR_CLASS_ERROR:
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        /* 25G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_25G_AOC:
+        case TRANSVR_CLASS_OPTICAL_25G_SR:
+        case TRANSVR_CLASS_OPTICAL_25G_LR:
+        case TRANSVR_CLASS_OPTICAL_25G_ER:
+        case TRANSVR_CLASS_OPTICAL_25G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_25G);
+        /* 25G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_25G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_25G);
+        /* 10G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_10G_S_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G_S_SR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_LR:
+        case TRANSVR_CLASS_OPTICAL_10G_S_ER:
+        case TRANSVR_CLASS_OPTICAL_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_10G);
+        /* 10G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_10G);
+        /* 1G OPTICAL */
+        case TRANSVR_CLASS_OPTICAL_1G_AOC:
+        case TRANSVR_CLASS_OPTICAL_1G_SX:
+        case TRANSVR_CLASS_OPTICAL_1G_LX:
+        case TRANSVR_CLASS_OPTICAL_1G_EX:
+        case TRANSVR_CLASS_OPTICAL_1G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_1G);
+        /* 1G COPPER */
+        case TRANSVR_CLASS_COPPER_L1_1G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_1G);
+        /* 1G BASE_T */
+        case TRANSVR_CLASS_BASE_T_1000:
+            return snprintf(result, lmax, TRANSVR_IF_SP_1G);
+        /* 100 Base */
+        case TRANSVR_CLASS_OPTICAL_100:
+            return snprintf(result, lmax, TRANSVR_IF_SP_100);
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined value:%d",
+                     detect_val);
+            goto err_sfp_detect_if_speed_1;
+    }
+    /* Check by BR */
+    detect_val = _sfp_detect_if_sp_by_br(self);
+    switch (detect_val) {
+        case TRANSVR_CLASS_25G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_25G);
+        case TRANSVR_CLASS_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_10G);
+        case TRANSVR_CLASS_1G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_1G);
+        default:
+            break;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg), "Can not identify!");
+    goto err_sfp_detect_if_speed_1;
+
+err_sfp_detect_if_speed_1:
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    SWPS_INFO("%s %s\n <port>:%s", __func__, err_msg, self->swp_name);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+sfp_get_if_speed(struct transvr_obj_s *self,
+                 char *buf_p){
+
+    int lmax = 16;
+    char tmp_result[16] = DEBUG_TRANSVR_STR_VAL;
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return snprintf(buf_p, lmax, "%d\n", self->state);
+    }
+    if (_sfp_detect_if_speed(self, tmp_result) < 0) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL);
+    }
+    return snprintf(buf_p, lmax, "%s\n", tmp_result);
+}
+
+
+int
+_qsfp_detect_class_by_extend_comp(struct transvr_obj_s* self) {
+    /* Reference: SFF-8024 (v3.8)
+     */
+    int detect_val = DEBUG_TRANSVR_INT_VAL;
+
+    detect_val = _qsfp_get_comp_extended(self);
+    switch(detect_val) {
+        case 0x00: /* Unspecified */
+            return TRANSVR_CLASS_UNSPECIFIED;
+
+        case 0x01: /* 100G AOC (Active Optical Cable) or 25GAUI C2M */
+        case 0x18: /* 100G AOC or 25GAUI C2M AOC. */
+            return TRANSVR_CLASS_OPTICAL_100G_AOC;
+
+        case 0x06: /* 100G CWDM4 */
+        case 0x09: /* Obsolete (assigned before 100G CWDM4 MSA required FEC) */
+        case 0x17: /* 100G CLR4 */
+        case 0x1A: /* 100GE-DWDM2 */
+            return TRANSVR_CLASS_OPTICAL_100G;
+
+        case 0x02: /* 100GBASE-SR4 or 25GBASE-SR */
+            return TRANSVR_CLASS_OPTICAL_100G_SR4;
+
+        case 0x03: /* 100GBASE-LR4 or 25GBASE-LR */
+            return TRANSVR_CLASS_OPTICAL_100G_LR4;
+
+        case 0x04: /* 100GBASE-ER4 or 25GBASE-ER */
+            return TRANSVR_CLASS_OPTICAL_100G_ER4;
+
+        case 0x07: /* 100G PSM4 Parallel SMF */
+            return TRANSVR_CLASS_OPTICAL_100G_PSM4;
+
+        case 0x12: /* 40G PSM4 Parallel SMF */
+            return TRANSVR_CLASS_OPTICAL_40G;
+
+        case 0x11: /* 4 x 10GBASE-SR */
+            return TRANSVR_CLASS_OPTICAL_40G_SR4;
+
+        case 0x10: /* 40GBASE-ER4 */
+            return TRANSVR_CLASS_OPTICAL_40G_ER4;
+
+        case 0x08: /* 100G ACC (Active Copper Cable) or 25GAUI C2M ACC. */
+        case 0x0b: /* 100GBASE-CR4 or 25GBASE-CR CA-L */
+        case 0x19: /* 100G ACC or 25GAUI C2M ACC. */
+            return TRANSVR_CLASS_COPPER_L4_100G;
+
+        default:
+            break;
+    }
+    SWPS_INFO("%s: Unexcept value:0x%02x\n <port>:%s",
+              __func__, detect_val, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+_qsfp_detect_class_by_10_40_100_ethernet(struct transvr_obj_s* self) {
+    /* Reference: SFF-8472 (v12.2)
+     */
+    int detect_val = DEBUG_TRANSVR_INT_VAL;
+
+    detect_val = _qsfp_get_comp_10_40_100_ethernet(self);
+    /* Case: Unspecified */
+    if (detect_val == 0x00) {
+        return TRANSVR_CLASS_UNSPECIFIED;
+    }
+    /* Case: 40G Optical */
+    if ((detect_val & 0x01) == 0x01) {    /* 00000001 : 40G Active Cable (XLPPI) */
+        return TRANSVR_CLASS_OPTICAL_40G_AOC;
+    }
+    if ((detect_val & 0x04) == 0x04) {    /* 00000100 : 40GBASE-SR4 */
+        return TRANSVR_CLASS_OPTICAL_40G_SR4;
+    }
+    if ( (detect_val & 0x02) == 0x02) {   /* 00000010 : 40GBASE-LR4 */
+        return TRANSVR_CLASS_OPTICAL_40G_LR4;
+    }
+    if ( (detect_val & 0x08) == 0x08) {   /* 00001000 : 40GBASE-CR4 */
+        return TRANSVR_CLASS_COPPER_L4_40G;
+    }
+    /* Case: 10G Optical */
+    if ( (detect_val & 0x10) == 0x10) {   /* 00010000 : 10GBASE-SR  */
+        return TRANSVR_CLASS_OPTICAL_10G_Q_SR;
+    }
+    if ( ((detect_val & 0x20) == 0x20) || /* 00100000 : 10GBASE-LR  */
+         ((detect_val & 0x40) == 0x40) ){ /* 01000000 : 10GBASE-LRM */
+        return TRANSVR_CLASS_OPTICAL_10G_Q_LR;
+    }
+    /* Case: Extend Compliance */
+    if ( ((detect_val & 0x80) == 0x80) ){ /* 10000000 : Use Extend Compliance */
+        return TRANSVR_CLASS_EXTEND_COMP;
+    }
+    /* Case: ERROR */
+    SWPS_INFO("%s: Unexcept value:0x%02x\n <port>:%s",
+              __func__, detect_val, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+_qsfp_detect_if_sp_by_br(struct transvr_obj_s* self) {
+
+    int lower_bound_10g  = 0x10;
+    int upper_bound_10g  = 0x25;
+    int lower_bound_40g  = 0x60;
+    int upper_bound_40g  = 0x75;
+    int lower_bound_100g = 0x60;
+    int upper_bound_100g = 0x75;
+    int used_extend_br   = 0xff;
+    int notmal_br = DEBUG_TRANSVR_INT_VAL;
+    int extend_br = DEBUG_TRANSVR_INT_VAL;
+
+    notmal_br = (int)(self->br); /* updated by update_all() */
+    /* Check 40G */
+    if ((notmal_br >= lower_bound_40g) &&
+        (notmal_br <= upper_bound_40g) ) {
+        return TRANSVR_CLASS_40G;
+    }
+    /* Check 100G */
+    if (notmal_br == used_extend_br) {
+        extend_br = (int)(self->extbr); /* updated by update_all() */
+        if ((extend_br >= lower_bound_100g) &&
+            (extend_br <= upper_bound_100g) ) {
+            return TRANSVR_CLASS_100G;
+        }
+    }
+    /* Check 10G */
+    if ((notmal_br >= lower_bound_10g) &&
+        (notmal_br <= upper_bound_10g) ) {
+        return TRANSVR_CLASS_10G;
+    }
+    return TRANSVR_CLASS_UNSPECIFIED;
+}
+
+
+int
+_qsfp_detect_class_by_feature(struct transvr_obj_s* self) {
+    /* Reference: SFF-8024 (v3.8)
+     */
+    int conn_val     = DEBUG_TRANSVR_INT_VAL;
+    int wave_len     = DEBUG_TRANSVR_INT_VAL;
+    int speed_val    = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    speed_val = _qsfp_detect_if_sp_by_br(self);
+    conn_val  = _qsfp_get_connector_type(self);
+
+    switch(conn_val) {
+        case 0x00: /* Unspecified */
+            return TRANSVR_CLASS_UNSPECIFIED;
+        case 0x07: /* LC (Lucent Connector) */
+        case 0x0b: /* Optical Pigtail */
+        case 0x0c: /* MPO 1x12 (Multifiber Parallel Optic) */
+        case 0x0d: /* MPO 2x16 */
+            goto ok_qsfp_detect_class_by_feature_4_optiocal;
+        case 0x21: /* Copper pigtail */
+            goto ok_qsfp_detect_class_by_feature_4_copper;
+        case 0x23: /* No separable connector */
+            if ((_qsfp_get_comp_fc_link_length(self) > 0) ||
+                (_qsfp_get_comp_fc_trans_tech(self) > 0)  ||
+                (_qsfp_get_comp_fc_trans_media(self) > 0) ||
+                (_qsfp_get_comp_fc_speed(self) > 0) ) {
+                goto ok_qsfp_detect_class_by_feature_4_aoc;
+            }
+            goto ok_qsfp_detect_class_by_feature_4_copper;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "_qsfp_get_connector_type return Non define value:%d",
+                     conn_val);
+            goto err_qsfp_detect_class_by_feature_1;
+    }
+    return TRANSVR_CLASS_UNSPECIFIED;
+
+ok_qsfp_detect_class_by_feature_4_optiocal:
+    wave_len  = _common_count_wavelength(self,
+                                         self->wavelength[0],
+                                         self->wavelength[1]);
+    switch(speed_val) {
+        case TRANSVR_CLASS_100G:
+            switch (wave_len) {
+                case VAL_OPTICAL_WAVELENGTH_SR:
+                    return TRANSVR_CLASS_OPTICAL_100G_SR4;
+                case VAL_OPTICAL_WAVELENGTH_LR:
+                    return TRANSVR_CLASS_OPTICAL_100G_LR4;
+                case VAL_OPTICAL_WAVELENGTH_ER:
+                    return TRANSVR_CLASS_OPTICAL_100G_ER4;
+                default:
+                    break;
+            }
+            return TRANSVR_CLASS_OPTICAL_100G;
+
+        case TRANSVR_CLASS_40G:
+            switch (wave_len) {
+                case VAL_OPTICAL_WAVELENGTH_SR:
+                    return TRANSVR_CLASS_OPTICAL_40G_SR4;
+                case VAL_OPTICAL_WAVELENGTH_LR:
+                    return TRANSVR_CLASS_OPTICAL_40G_LR4;
+                case VAL_OPTICAL_WAVELENGTH_ER:
+                    return TRANSVR_CLASS_OPTICAL_40G_ER4;
+                default:
+                    break;
+            }
+            return TRANSVR_CLASS_OPTICAL_40G;
+
+        case TRANSVR_CLASS_10G:
+            switch (wave_len) {
+                case VAL_OPTICAL_WAVELENGTH_SR:
+                    return TRANSVR_CLASS_OPTICAL_10G_Q_SR;
+                case VAL_OPTICAL_WAVELENGTH_LR:
+                    return TRANSVR_CLASS_OPTICAL_10G_Q_LR;
+                case VAL_OPTICAL_WAVELENGTH_ER:
+                    return TRANSVR_CLASS_OPTICAL_10G_Q_ER;
+                default:
+                    break;
+            }
+            return TRANSVR_CLASS_OPTICAL_10G;
+
+        default:
+            return TRANSVR_CLASS_OPTICAL;
+    }
+
+ok_qsfp_detect_class_by_feature_4_aoc:
+    switch(speed_val) {
+        case TRANSVR_CLASS_100G:
+            return TRANSVR_CLASS_OPTICAL_100G_AOC;
+        case TRANSVR_CLASS_40G:
+            return TRANSVR_CLASS_OPTICAL_40G_AOC;
+        case TRANSVR_CLASS_10G:
+            return TRANSVR_CLASS_OPTICAL_10G_Q_AOC;
+        default:
+            return TRANSVR_CLASS_OPTICAL;
+    }
+
+ok_qsfp_detect_class_by_feature_4_copper:
+    switch(speed_val) {
+        case TRANSVR_CLASS_100G:
+            return TRANSVR_CLASS_COPPER_L4_100G;
+        case TRANSVR_CLASS_40G:
+            return TRANSVR_CLASS_COPPER_L4_40G;
+        case TRANSVR_CLASS_10G:
+            return TRANSVR_CLASS_COPPER_L4_10G;
+        default:
+            return TRANSVR_CLASS_COPPER;
+    }
+
+err_qsfp_detect_class_by_feature_1:
+    SWPS_INFO("%s: %s\n <port>:%s",
+              __func__, err_msg, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+qsft_detect_transvr_class(struct transvr_obj_s* self) {
+
+    int detect_val   = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    /* Check Extended Compliance */
+    detect_val = _qsfp_detect_class_by_extend_comp(self);
+    switch (detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_OPTICAL_100G:
+        case TRANSVR_CLASS_OPTICAL_100G_AOC:
+        case TRANSVR_CLASS_OPTICAL_100G_SR4:
+        case TRANSVR_CLASS_OPTICAL_100G_LR4:
+        case TRANSVR_CLASS_OPTICAL_100G_ER4:
+        case TRANSVR_CLASS_OPTICAL_100G_PSM4:
+        case TRANSVR_CLASS_OPTICAL_40G:
+        case TRANSVR_CLASS_OPTICAL_40G_AOC:
+        case TRANSVR_CLASS_OPTICAL_40G_SR4:
+        case TRANSVR_CLASS_OPTICAL_40G_LR4:
+        case TRANSVR_CLASS_OPTICAL_40G_ER4:
+        case TRANSVR_CLASS_COPPER_L4_100G:
+            return detect_val;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined extend_comp:%d",
+                     detect_val);
+            goto err_qsft_detect_transvr_class_1;
+    }
+    /* Check 10/40G/100G Ethernet Compliance */
+    detect_val = _qsfp_detect_class_by_10_40_100_ethernet(self);
+    switch(detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_OPTICAL_40G_AOC:
+        case TRANSVR_CLASS_OPTICAL_40G_SR4:
+        case TRANSVR_CLASS_OPTICAL_40G_LR4:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */
+        case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */
+        case TRANSVR_CLASS_COPPER_L4_40G:
+            return detect_val;
+        case TRANSVR_CLASS_EXTEND_COMP:
+            /* Format incorrect case (We already checked the Extend
+             * Compliance is 0
+             */
+            snprintf(err_msg, sizeof(err_msg),
+                    "Transceiver format incorrect");
+            goto err_qsft_detect_transvr_class_1;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined 10/40/100:%d",
+                     detect_val);
+            goto err_qsft_detect_transvr_class_1;
+    }
+    /* Check by Connector type, BR and wavelength */
+    detect_val = _qsfp_detect_class_by_feature(self);
+    switch (detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_OPTICAL_100G_ER4:
+        case TRANSVR_CLASS_OPTICAL_100G_LR4:
+        case TRANSVR_CLASS_OPTICAL_100G_SR4:
+        case TRANSVR_CLASS_OPTICAL_100G_AOC:
+        case TRANSVR_CLASS_OPTICAL_100G:
+        case TRANSVR_CLASS_OPTICAL_40G_ER4:
+        case TRANSVR_CLASS_OPTICAL_40G_LR4:
+        case TRANSVR_CLASS_OPTICAL_40G_SR4:
+        case TRANSVR_CLASS_OPTICAL_40G_AOC:
+        case TRANSVR_CLASS_OPTICAL_40G:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_ER:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_LR:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_SR:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G:
+        case TRANSVR_CLASS_OPTICAL:
+        case TRANSVR_CLASS_COPPER_L4_100G:
+        case TRANSVR_CLASS_COPPER_L4_40G:
+        case TRANSVR_CLASS_COPPER_L4_10G:
+        case TRANSVR_CLASS_COPPER:
+            return detect_val;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined connector:%d",
+                     detect_val);
+            goto err_qsft_detect_transvr_class_1;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg),
+            "Can not identify!");
+    goto err_qsft_detect_transvr_class_1;
+
+err_qsft_detect_transvr_class_1:
+    SWPS_INFO("%s: %s\n <port>:%s", __func__, err_msg, self->swp_name);
+    return TRANSVR_CLASS_ERROR;
+}
+
+
+int
+_qsfp_set_trident2_if_type(struct transvr_obj_s* self,
+                           int transvr_cls,
+                           char *result){
+
+    int lmax = 8;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    switch (transvr_cls) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+        case TRANSVR_CLASS_ERROR:
+            break;
+        /* 100G Optical */
+        case TRANSVR_CLASS_OPTICAL_100G:
+        case TRANSVR_CLASS_OPTICAL_100G_AOC:
+        case TRANSVR_CLASS_OPTICAL_100G_SR4:
+        case TRANSVR_CLASS_OPTICAL_100G_LR4:
+        case TRANSVR_CLASS_OPTICAL_100G_ER4:
+        case TRANSVR_CLASS_OPTICAL_100G_PSM4:
+            return snprintf(result, lmax, TRANSVR_IF_SR4);
+        /* 100G Copper */
+        case TRANSVR_CLASS_COPPER_L4_100G:
+            return snprintf(result, lmax, TRANSVR_IF_KR4);
+        /* 40G Optical */
+        case TRANSVR_CLASS_OPTICAL_40G:
+        case TRANSVR_CLASS_OPTICAL_40G_AOC:
+        case TRANSVR_CLASS_OPTICAL_40G_SR4:
+        case TRANSVR_CLASS_OPTICAL_40G_LR4:
+        case TRANSVR_CLASS_OPTICAL_40G_ER4:
+            return snprintf(result, lmax, TRANSVR_IF_IF_XGMII);
+        /* 40G Copper */
+        case TRANSVR_CLASS_COPPER_L4_40G:
+            return snprintf(result, lmax, TRANSVR_IF_IF_XGMII);
+        /* 10G Optical */
+        case TRANSVR_CLASS_OPTICAL_10G:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */
+        case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: LR4 or LR */
+        case TRANSVR_CLASS_OPTICAL_10G_Q_ER: /* Need Check: ER4 or ER */
+            return snprintf(result, lmax, TRANSVR_IF_IF_XGMII);
+        /* Optical */
+        case TRANSVR_CLASS_OPTICAL:
+            return snprintf(result, lmax, TRANSVR_IF_IF_XGMII);
+        /* Copper */
+        case TRANSVR_CLASS_COPPER:
+            return snprintf(result, lmax, TRANSVR_IF_IF_XGMII);
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined value:%d",
+                     transvr_cls);
+            goto err_qsfp_set_trident2_if_type_1;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg), "Can not identify!");
+    goto err_qsfp_set_trident2_if_type_1;
+
+err_qsfp_set_trident2_if_type_1:
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    SWPS_INFO("%s: %s\n <port>:%s", __func__, err_msg, self->swp_name);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_qsfp_set_tomahawk_if_type(struct transvr_obj_s* self,
+                           int transvr_cls,
+                           char *result){
+
+    int lmax = 8;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    switch (transvr_cls) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+        case TRANSVR_CLASS_ERROR:
+            break;
+        /* 100G Optical */
+        case TRANSVR_CLASS_OPTICAL_100G:
+        case TRANSVR_CLASS_OPTICAL_100G_AOC:
+        case TRANSVR_CLASS_OPTICAL_100G_SR4:
+        case TRANSVR_CLASS_OPTICAL_100G_LR4:
+        case TRANSVR_CLASS_OPTICAL_100G_ER4:
+        case TRANSVR_CLASS_OPTICAL_100G_PSM4:
+            return snprintf(result, lmax, TRANSVR_IF_SR4);
+        /* 100G Copper */
+        case TRANSVR_CLASS_COPPER_L4_100G:
+            return snprintf(result, lmax, TRANSVR_IF_KR4);
+        /* 40G Optical */
+        case TRANSVR_CLASS_OPTICAL_40G:
+        case TRANSVR_CLASS_OPTICAL_40G_AOC:
+        case TRANSVR_CLASS_OPTICAL_40G_SR4:
+        case TRANSVR_CLASS_OPTICAL_40G_LR4:
+        case TRANSVR_CLASS_OPTICAL_40G_ER4:
+            return snprintf(result, lmax, TRANSVR_IF_SR4);
+        /* 40G Copper */
+        case TRANSVR_CLASS_COPPER_L4_40G:
+            return snprintf(result, lmax, TRANSVR_IF_KR4);
+        /* 10G Optical */
+        case TRANSVR_CLASS_OPTICAL_10G:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */
+        case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */
+        case TRANSVR_CLASS_OPTICAL_10G_Q_ER:
+            return snprintf(result, lmax, TRANSVR_IF_SR4);
+        /* Optical */
+        case TRANSVR_CLASS_OPTICAL:
+            return snprintf(result, lmax, TRANSVR_IF_SR4);
+        /* Copper */
+        case TRANSVR_CLASS_COPPER:
+            return snprintf(result, lmax, TRANSVR_IF_KR4);
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined value:%d",
+                     transvr_cls);
+            goto err_qsfp_set_trident2_if_type_1;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg), "Can not identify!");
+    goto err_qsfp_set_trident2_if_type_1;
+
+err_qsfp_set_trident2_if_type_1:
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    SWPS_INFO("%s: %s\n <port>:%s", __func__, err_msg, self->swp_name);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+_qsfp_set_bf_tofino_if_type(struct transvr_obj_s* self,
+                            int transvr_cls,
+                            char *result) {
+    /* (TBD)
+     *  Due to BF looks like doesn't have interface type.
+     *  We bypass it currently.
+     */
+    int lmax = 8;    
+    return snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+}
+
+
+int
+_qsfp_detect_if_type(struct transvr_obj_s* self,
+                     char *result){
+
+    int lmax = 8;
+    int detect_cls = DEBUG_TRANSVR_INT_VAL;
+
+    detect_cls = qsft_detect_transvr_class(self);
+    switch (self->chipset_type) {
+        case BCM_CHIP_TYPE_TRIDENT_2:
+            return _qsfp_set_trident2_if_type(self, detect_cls, result);
+        
+        case BCM_CHIP_TYPE_TRIDENT_3:
+        case BCM_CHIP_TYPE_TOMAHAWK:
+            return _qsfp_set_tomahawk_if_type(self, detect_cls, result);
+
+        case BF_CHIP_TYPE_TOFINO:
+            return _qsfp_set_bf_tofino_if_type(self, detect_cls, result);
+            
+        default:
+            SWPS_INFO("%s: non-defined chipset_type:%d <port>:%s\n",
+                      __func__, self->chipset_type, self->swp_name);
+            break;
+    }
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+qsfp_get_if_type(struct transvr_obj_s *self,
+                 char *buf_p){
+
+    int lmax = 8;
+    char tmp_result[8] = DEBUG_TRANSVR_STR_VAL;
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return snprintf(buf_p, lmax, "%d\n", self->state);
+    }
+    if (_qsfp_detect_if_type(self, tmp_result) < 0) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL);
+    }
+    return snprintf(buf_p, lmax, "%s\n", tmp_result);
+}
+
+
+int
+_qsfp_detect_if_speed(struct transvr_obj_s* self,
+                      char *result){
+    int lmax = 16;
+    int detect_val   = DEBUG_TRANSVR_INT_VAL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    detect_val = qsft_detect_transvr_class(self);
+    switch (detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+        case TRANSVR_CLASS_ERROR:
+            break;
+        /* 100G Optical */
+        case TRANSVR_CLASS_OPTICAL_100G:
+        case TRANSVR_CLASS_OPTICAL_100G_AOC:
+        case TRANSVR_CLASS_OPTICAL_100G_SR4:
+        case TRANSVR_CLASS_OPTICAL_100G_LR4:
+        case TRANSVR_CLASS_OPTICAL_100G_ER4:
+        case TRANSVR_CLASS_OPTICAL_100G_PSM4:
+            return snprintf(result, lmax, TRANSVR_IF_SP_100G);
+        /* 100G Copper */
+        case TRANSVR_CLASS_COPPER_L4_100G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_100G);
+        /* 40G Optical */
+        case TRANSVR_CLASS_OPTICAL_40G:
+        case TRANSVR_CLASS_OPTICAL_40G_AOC:
+        case TRANSVR_CLASS_OPTICAL_40G_SR4:
+        case TRANSVR_CLASS_OPTICAL_40G_LR4:
+        case TRANSVR_CLASS_OPTICAL_40G_ER4:
+            return snprintf(result, lmax, TRANSVR_IF_SP_40G);
+        /* 40G Copper */
+        case TRANSVR_CLASS_COPPER_L4_40G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_40G);
+        /* 10G Optical */
+        case TRANSVR_CLASS_OPTICAL_10G:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_AOC:
+        case TRANSVR_CLASS_OPTICAL_10G_Q_SR: /* Need Check: SR4 or SR */
+        case TRANSVR_CLASS_OPTICAL_10G_Q_LR: /* Need Check: SR4 or SR */
+        case TRANSVR_CLASS_OPTICAL_10G_Q_ER:
+            return snprintf(result, lmax, TRANSVR_IF_SP_10G);
+        /* 10G Copper */
+        case TRANSVR_CLASS_COPPER_L4_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_10G);
+        /* Optical */
+        case TRANSVR_CLASS_OPTICAL:
+            break;
+        /* Copper */
+        case TRANSVR_CLASS_COPPER:
+            break;
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined class case:%d",
+                     detect_val);
+            goto err_qsfp_detect_if_speed_1;
+    }
+    /* Check br and extbr */
+    detect_val = _qsfp_detect_if_sp_by_br(self);
+    switch(detect_val) {
+        case TRANSVR_CLASS_UNSPECIFIED:
+            break;
+        case TRANSVR_CLASS_10G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_10G);
+        case TRANSVR_CLASS_40G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_40G);
+        case TRANSVR_CLASS_100G:
+            return snprintf(result, lmax, TRANSVR_IF_SP_100G);
+        default:
+            snprintf(err_msg, sizeof(err_msg),
+                     "Detect undefined BR case:%d",
+                     detect_val);
+            goto err_qsfp_detect_if_speed_1;
+    }
+    /* Exception case: Can't verify */
+    snprintf(err_msg, sizeof(err_msg), "Can not identify!");
+    goto err_qsfp_detect_if_speed_1;
+
+err_qsfp_detect_if_speed_1:
+    snprintf(result, lmax, TRANSVR_UEVENT_UNKNOW);
+    SWPS_INFO("%s: %s <port>:%s\n", __func__, err_msg, self->swp_name);
+    return ERR_TRANSVR_ABNORMAL;
+}
+
+
+int
+qsfp_get_if_speed(struct transvr_obj_s *self,
+                 char *buf_p){
+
+    int lmax = 16;
+    char tmp_result[16] = DEBUG_TRANSVR_STR_VAL;
+
+    if (self->state != STATE_TRANSVR_CONNECTED) {
+        return snprintf(buf_p, lmax, "%d\n", self->state);
+    }
+    if (_qsfp_detect_if_speed(self, tmp_result) < 0) {
+        return snprintf(buf_p, lmax, "%d\n", ERR_TRANSVR_ABNORMAL);
+    }
+    return snprintf(buf_p, lmax, "%s\n", tmp_result);
+}
+
+
+int
+_common_set_lane_map_str(struct transvr_obj_s* self,
+                         char *result) {
+    int  i = 0;
+    int  tmp_val = 0;
+    char tmp_str[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL;
+    char err_msg[LEN_TRANSVR_L_STR] = DEBUG_TRANSVR_STR_VAL;
+
+    memset(result, 0, LEN_TRANSVR_L_STR);
+    snprintf(result, LEN_TRANSVR_L_STR, "%s=", TRANSVR_UEVENT_KEY_LANE);
+
+    for (i=0; i<ARRAY_SIZE(self->lane_id); i++) {
+        tmp_val = self->lane_id[i];
+        if (tmp_val < 1) {
+            break;
+        }
+        if (tmp_val > 256) {
+            snprintf(err_msg, sizeof(err_msg),
+                    "detect abnormal value:%d", tmp_val);
+            goto err_common_set_lane_map_str_1;
+        }
+        memset(tmp_str, 0, sizeof(tmp_str));
+        if (i == 0) {
+            snprintf(tmp_str, LEN_TRANSVR_L_STR, "%d", tmp_val);
+        } else {
+            snprintf(tmp_str, LEN_TRANSVR_L_STR, ",%d", tmp_val);
+        }
+        strncat(result, tmp_str, LEN_TRANSVR_L_STR);
+    }
+    if (i == 0) {
+        goto err_common_set_lane_map_str_2;
+    }
+    return 0;
+
+err_common_set_lane_map_str_1:
+    SWPS_INFO("%s: %s", __func__, err_msg);
+err_common_set_lane_map_str_2:
+    snprintf(result, LEN_TRANSVR_L_STR, "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW);
+    return EVENT_TRANSVR_TASK_FAIL;
+}
+
+
+int
+_common_send_uevent(struct transvr_obj_s* self,
+                    enum kobject_action u_action,
+                    int (*detect_if_type)(struct transvr_obj_s *self, char *result),
+                    int (*detect_if_speed)(struct transvr_obj_s *self, char *result),
+                    int send_anyway) {
+
+    char *uevent_envp[4];
+    char err_msg[64]   = DEBUG_TRANSVR_STR_VAL;
+    char tmp_str[32]   = DEBUG_TRANSVR_STR_VAL;
+    char tmp_str_1[32] = DEBUG_TRANSVR_STR_VAL;
+    char tmp_str_2[32] = DEBUG_TRANSVR_STR_VAL;
+    char tmp_str_3[64] = DEBUG_TRANSVR_STR_VAL;
+
+    if (TRANSVR_UEVENT_ENABLE != 1) {
+        return ERR_TRANSVR_NOTSUPPORT;
+    }
+    if (_common_get_if_lane(self, tmp_str) < 0) {
+        snprintf(tmp_str_3, sizeof(tmp_str_3),
+                "%s=%s", TRANSVR_UEVENT_KEY_LANE, TRANSVR_UEVENT_UNKNOW);
+    } else {
+        snprintf(tmp_str_3, sizeof(tmp_str_3),
+                "%s=%s", TRANSVR_UEVENT_KEY_LANE, tmp_str);
+    }
+    switch (u_action) {
+        case KOBJ_ADD:
+            /* Detect type */
+            if (detect_if_type(self, tmp_str) < 0) {
+                snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface type fail!");
+                snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW);
+                snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW);
+                uevent_envp[0] = tmp_str_1;
+                uevent_envp[1] = tmp_str_2;
+                uevent_envp[2] = tmp_str_3;
+                uevent_envp[3] = NULL;
+                goto private_common_send_uevent_4_fail;
+            }
+            snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, tmp_str);
+            uevent_envp[0] = tmp_str_1;
+            /* Detect speed */
+            if (detect_if_speed(self, tmp_str) < 0) {
+                snprintf(err_msg, sizeof(err_msg), "%s", "Detect interface speed fail!");
+                snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW);
+                uevent_envp[1] = tmp_str_2;
+                uevent_envp[2] = tmp_str_3;
+                uevent_envp[3] = NULL;
+                goto private_common_send_uevent_4_fail;
+            }
+            snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, tmp_str);
+            uevent_envp[1] = tmp_str_2;
+            uevent_envp[2] = tmp_str_3;
+            uevent_envp[3] = NULL;
+            goto private_common_send_uevent_4_send;
+
+        case KOBJ_REMOVE:
+            snprintf(tmp_str_1, sizeof(tmp_str_1), "%s=%s", TRANSVR_UEVENT_KEY_IF, TRANSVR_UEVENT_UNKNOW);
+            snprintf(tmp_str_2, sizeof(tmp_str_2), "%s=%s", TRANSVR_UEVENT_KEY_SP, TRANSVR_UEVENT_UNKNOW);
+            uevent_envp[0] = tmp_str_1;
+            uevent_envp[1] = tmp_str_2;
+            uevent_envp[2] = tmp_str_3;
+            uevent_envp[3] = NULL;
+            goto private_common_send_uevent_4_send;
+
+        default:
+            snprintf(err_msg, sizeof(err_msg), "kobject_action:%d not support", u_action);
+            goto private_common_send_uevent_4_fail;
+    }
+    snprintf(err_msg, sizeof(err_msg), "%s", "Exception case");
+    goto private_common_send_uevent_4_fail;
+
+private_common_send_uevent_4_fail:
+    SWPS_INFO("%s: %s <port>:%s\n", __func__, err_msg, self->swp_name);
+    if (send_anyway) {
+        goto private_common_send_uevent_4_send;
+    }
+    return ERR_TRANSVR_UEVENT_FAIL;
+
+private_common_send_uevent_4_send:
+    return kobject_uevent_env(&(self->transvr_dev_p->kobj),
+                              u_action,
+                              uevent_envp);
+}
+
+int
+sfp_send_uevent(struct transvr_obj_s* self,
+                enum kobject_action u_action) {
+    int send_anyway = 1;
+    return _common_send_uevent(self,
+                               u_action,
+                               &_sfp_detect_if_type,
+                               &_sfp_detect_if_speed,
+                               send_anyway);
+}
+
+
+int
+qsfp_send_uevent(struct transvr_obj_s* self,
+                enum kobject_action u_action) {
+    int send_anyway = 1;
+    return _common_send_uevent(self,
+                               u_action,
+                               &_qsfp_detect_if_type,
+                               &_qsfp_detect_if_speed,
+                               send_anyway);
+}
+
+
+int
+fake_send_uevent(struct transvr_obj_s* self,
+                 enum kobject_action u_action) {
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+common_fsm_4_direct_mode(struct transvr_obj_s* self,
+                         char *caller_name){
+
+    int err;
+    int detect_result[2];
+    int current_state = STATE_TRANSVR_UNEXCEPTED;
+    int current_type  = TRANSVR_TYPE_ERROR;
+
+    if (self->state == STATE_TRANSVR_NEW) {
+        if (_transvr_init_handler(self) < 0){
+            return ERR_TRANSVR_INIT_FAIL;
+        }
+    }
+    err = detect_transvr_state(self, detect_result);
+    if (err < 0) {
+        return err;
+    }
+    /* In Direct mode, driver only detect transceiver when user call driver interface
+     * which on sysfs. So it only need consider the state of Transceiver.
+     */
+    current_state = detect_result[0];
+    current_type  = detect_result[1];
+
+    switch (current_state){
+
+        case STATE_TRANSVR_DISCONNECTED:   /* Transceiver is not plugged */
+            self->state = current_state;
+            self->type  = current_type;
+            return ERR_TRANSVR_UNPLUGGED;
+
+        case STATE_TRANSVR_INIT:           /* Transceiver is plugged, system not ready */
+            return ERR_TRANSVR_UNINIT;
+
+        case STATE_TRANSVR_ISOLATED:       /* Transceiver is plugged, but has some issues */
+            return ERR_TRNASVR_BE_ISOLATED;
+
+        case STATE_TRANSVR_CONNECTED:      /* Transceiver is plugged, system is ready */
+            self->state = current_state;
+            self->type  = current_type;
+            return 0;
+
+        case STATE_TRANSVR_SWAPPED:        /* Transceiver is plugged, system detect user changed */
+            self->type = current_type;
+            if (reload_transvr_obj(self, current_type) < 0){
+                self->state = STATE_TRANSVR_UNEXCEPTED;
+                return ERR_TRANSVR_UNEXCPT;
+            }
+            self->state = current_state;
+            return 0;
+
+        case STATE_TRANSVR_UNEXCEPTED:     /* Transceiver type or state is unexpected case */
+            self->state = STATE_TRANSVR_UNEXCEPTED;
+            self->type  = TRANSVR_TYPE_ERROR;
+            return ERR_TRANSVR_UNEXCPT;
+
+        default:
+            SWPS_INFO("%s: state:%d not in define.\n", __func__, current_state);
+            break;
+    }
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+static int
+_is_except_happened_4_pmode(struct transvr_obj_s* self,
+                            int new_state) {
+
+    int event_chk = 0;
+
+    if (self->temp == 0){
+        return 0;
+    }
+    switch (new_state) {
+        case STATE_TRANSVR_INIT:
+            event_chk = EVENT_TRANSVR_EXCEP_INIT;
+            goto check_event_happened_4_pmode;
+
+        case STATE_TRANSVR_CONNECTED:
+            event_chk = EVENT_TRANSVR_EXCEP_UP;
+            goto check_event_happened_4_pmode;
+
+        case STATE_TRANSVR_DISCONNECTED:
+            event_chk = EVENT_TRANSVR_EXCEP_DOWN;
+            goto check_event_happened_4_pmode;
+
+        case STATE_TRANSVR_SWAPPED:
+            event_chk = EVENT_TRANSVR_EXCEP_SWAP;
+            goto check_event_happened_4_pmode;
+
+        case STATE_TRANSVR_UNEXCEPTED:
+            event_chk = EVENT_TRANSVR_EXCEP_EXCEP;
+            goto check_event_happened_4_pmode;
+
+        case STATE_TRANSVR_ISOLATED:
+            event_chk = EVENT_TRANSVR_EXCEP_ISOLATED;
+            goto check_event_happened_4_pmode;
+
+        default:
+            SWPS_INFO("%s: unexcepted case:%d\n", __func__, new_state);
+            break;
+    }
+    return 0;
+
+check_event_happened_4_pmode:
+    if (self->temp == event_chk){
+        return 1;
+    }
+    return 0;
+}
+
+
+int
+common_fsm_4_polling_mode(struct transvr_obj_s* self,
+                          char *caller_name){
+    /* [Return Value]:
+     *   ERR_TRANSVR_UNINIT      : (1) Initial not ready
+     *   ERR_TRANSVR_UNPLUGGED   : (1) Any -> Down
+     *   ERR_TRANSVR_TASK_BUSY   : (1) Wait Initial task
+     *   ERR_TRANSVR_UNEXCPT     : (1) Initial fail
+     *                             (2) Task fail
+     *                             (3) Reload fail
+     *   ERR_TRNASVR_BE_ISOLATED : (1) Already be isolated
+     *   OK Case (return 0)      : (1) action_4_connected
+     *                             (2) action_4_nothing (initial retry)
+     */
+    int curr_state[2];
+    int old_state  = self->state;
+    int old_type   = self->type;
+    int new_state  = STATE_TRANSVR_UNEXCEPTED;
+    int new_type   = TRANSVR_TYPE_ERROR;
+    int return_val = ERR_TRANSVR_UNEXCPT;
+
+    /* Never initial */
+    if (self->state == STATE_TRANSVR_NEW) {
+        goto comfsm_action_4_reinit_obj;
+    }
+    /* Detect current state */
+    switch (detect_transvr_state(self, curr_state)) {
+      case 0:
+          new_state = curr_state[0];
+          new_type  = curr_state[1];
+          break;
+
+      case ERR_TRNASVR_BE_ISOLATED:
+          new_state = STATE_TRANSVR_ISOLATED;
+          new_type  = old_type;
+          break;
+
+      case ERR_TRANSVR_I2C_CRASH:
+          goto comfsm_action_4_report_i2c_crash;
+
+      case ERR_TRANSVR_UNEXCPT:
+      default:
+          new_state = STATE_TRANSVR_UNEXCEPTED;
+          new_type  = old_type;
+    }
+    /* State handling  */
+    switch (old_state) {
+       case STATE_TRANSVR_INIT:                  /* INIT -> <ANY> */
+           return_val = ERR_TRANSVR_UNINIT;
+           goto comfsm_action_4_keep_state;
+
+       case STATE_TRANSVR_CONNECTED:
+           switch (new_state) {
+               case STATE_TRANSVR_INIT:          /* Case 1-1: UP -> INIT */
+                   SWPS_INFO("Detect %s is present. <case>:1-1\n",self->swp_name);
+                   return_val = ERR_TRANSVR_UNINIT;
+                   goto comfsm_action_4_keep_state;
+
+               case STATE_TRANSVR_CONNECTED:     /* Case 1-2: UP -> UP */
+                   return_val = 0;
+                   goto comfsm_action_4_keep_state;
+
+               case STATE_TRANSVR_DISCONNECTED:  /* Case 1-3: UP -> DOWN */
+                   SWPS_INFO("Detect %s is removed. <case>:1-3\n",self->swp_name);
+                   goto comfsm_action_4_disconnected;
+
+               case STATE_TRANSVR_SWAPPED:       /* Case 1-4: UP -> SWAP */
+                   SWPS_INFO("Detect %s is swapped. <case>:1-4\n",self->swp_name);
+                   goto comfsm_action_4_reload_obj;
+
+               case STATE_TRANSVR_UNEXCEPTED:    /* Case 1-5: UP -> UNEXPET */
+                   SWPS_INFO("Detect %s has error. <case>:1-5\n",self->swp_name);
+                   goto comfsm_action_4_unexpected;
+
+               case STATE_TRANSVR_ISOLATED:      /* Case 1-6: UP -> ISOLATE */
+                   SWPS_INFO("Detect %s be isolated. <case>:1-6\n",self->swp_name);
+                   goto comfsm_action_4_isolate_obj;
+
+               default:
+                   break;
+           }
+           goto comfsm_action_4_unexpected;
+
+       case STATE_TRANSVR_DISCONNECTED:
+           switch (new_state) {
+               case STATE_TRANSVR_INIT:          /* Case 2-1: DOWN -> INIT */
+                   SWPS_INFO("Detect %s is present. <case>:2-1\n",self->swp_name);
+                   return_val   = ERR_TRANSVR_UNINIT;
+                   goto comfsm_action_4_keep_state;
+
+               case STATE_TRANSVR_CONNECTED:     /* Case 2-2: DOWN -> UP */
+                   SWPS_INFO("Detect %s is present. <case>:2-2\n",self->swp_name);
+                   goto comfsm_action_4_reinit_obj;
+
+               case STATE_TRANSVR_DISCONNECTED:  /* Case 2-3: DOWN -> DOWN */
+                   return_val = ERR_TRANSVR_UNPLUGGED;
+                   goto comfsm_action_4_keep_state;
+
+               case STATE_TRANSVR_SWAPPED:       /* Case 2-4: DOWN -> SWAP */
+                   SWPS_INFO("Detect %s is swapped. <case>:2-4\n",self->swp_name);
+                   goto comfsm_action_4_reload_obj;
+
+               case STATE_TRANSVR_UNEXCEPTED:    /* Case 2-5: DOWN -> UNEXPET */
+                   SWPS_INFO("Detect %s has error. <case>:2-5\n",self->swp_name);
+                   goto comfsm_action_4_unexpected;
+
+               case STATE_TRANSVR_ISOLATED:      /* Case 2-6: DOWN -> ISOLATE */
+                   SWPS_INFO("Detect %s be isolated. <case>:2-6\n",self->swp_name);
+                   goto comfsm_action_4_isolate_obj;
+
+               default:
+                   break;
+           }
+           goto comfsm_action_4_unexpected;
+
+       case STATE_TRANSVR_UNEXCEPTED:
+           /* Filter out re-action */
+           if (_is_except_happened_4_pmode(self, new_state)) {
+               goto comfsm_action_4_keep_state;
+           }
+           /* First action */
+           switch (new_state) {
+               case STATE_TRANSVR_INIT:          /* Case 3-1: UNEXPET -> INIT */
+                   SWPS_INFO("Detect %s is present. <case>:3-1\n",self->swp_name);
+                   self->temp = EVENT_TRANSVR_EXCEP_INIT;
+                   return_val = ERR_TRANSVR_UNINIT;
+                   goto comfsm_action_4_keep_state;
+
+               case STATE_TRANSVR_CONNECTED:     /* Case 3-2: UNEXPET -> UP */
+                   SWPS_INFO("Detect %s is present. <case>:3-2\n",self->swp_name);
+                   self->temp = EVENT_TRANSVR_EXCEP_UP;
+                   goto comfsm_action_4_reload_obj;
+
+               case STATE_TRANSVR_DISCONNECTED:  /* Case 3-3: UNEXPET -> DOWN */
+                   SWPS_INFO("Detect %s is removed. <case>:3-3\n",self->swp_name);
+                   goto comfsm_action_4_disconnected;
+
+               case STATE_TRANSVR_SWAPPED:       /* Case 3-4: UNEXPET -> SWAP */
+                   SWPS_INFO("Detect %s is swapped. <case>:3-4\n",self->swp_name);
+                   self->temp = EVENT_TRANSVR_EXCEP_SWAP;
+                   goto comfsm_action_4_reload_obj;
+
+               case STATE_TRANSVR_UNEXCEPTED:    /* Case 3-5: UNEXPET -> UNEXPET */
+                   self->temp = EVENT_TRANSVR_EXCEP_EXCEP;
+                   return_val = ERR_TRANSVR_UNEXCPT;
+                   goto comfsm_action_4_keep_state;
+
+               case STATE_TRANSVR_ISOLATED:      /* Case 3-6: UNEXPET -> ISOLATE */
+                   SWPS_INFO("Detect %s be isolated. <case>:3-6\n",self->swp_name);
+                   goto comfsm_action_4_isolate_obj;
+
+               default:
+                   break;
+           }
+           goto comfsm_action_4_unexpected;
+
+        case STATE_TRANSVR_ISOLATED:
+            /* Filter out re-action */
+            if (_is_except_happened_4_pmode(self, new_state)) {
+                goto comfsm_action_4_keep_state;
+            }
+            /* First action */
+            switch (new_state) {
+                case STATE_TRANSVR_INIT:          /* Case 4-1: ISOLATE -> INIT */
+                    SWPS_INFO("Detect %s internal error. <case>:4-1\n",self->swp_name);
+                    self->temp = EVENT_TRANSVR_EXCEP_INIT;
+                    return_val = ERR_TRNASVR_BE_ISOLATED;
+                    goto comfsm_action_4_keep_state;
+
+                case STATE_TRANSVR_CONNECTED:     /* Case 4-2: ISOLATE -> UP */
+                    SWPS_INFO("Detect %s internal error. <case>:4-2\n",self->swp_name);
+                    self->temp = EVENT_TRANSVR_EXCEP_UP;
+                    return_val = ERR_TRNASVR_BE_ISOLATED;
+                    goto comfsm_action_4_keep_state;
+
+                case STATE_TRANSVR_DISCONNECTED:  /* Case 4-3: ISOLATE -> DOWN */
+                    SWPS_INFO("Detect %s is removed. <case>:4-3\n",self->swp_name);
+                    goto comfsm_action_4_disconnected;
+
+                case STATE_TRANSVR_SWAPPED:       /* Case 4-4: ISOLATE -> SWAP */
+                    SWPS_INFO("Detect %s internal error. <case>:4-4\n",self->swp_name);
+                    self->temp = EVENT_TRANSVR_EXCEP_SWAP;
+                    return_val = ERR_TRNASVR_BE_ISOLATED;
+                    goto comfsm_action_4_keep_state;
+
+                case STATE_TRANSVR_UNEXCEPTED:    /* Case 4-5: ISOLATE -> UNEXPET */
+                    SWPS_INFO("Detect %s internal error. <case>:4-5\n",self->swp_name);
+                    self->temp = EVENT_TRANSVR_EXCEP_EXCEP;
+                    return_val = ERR_TRNASVR_BE_ISOLATED;
+                    goto comfsm_action_4_keep_state;
+
+                case STATE_TRANSVR_ISOLATED:      /* Case 4-6: ISOLATE -> ISOLATE */
+                    return_val = ERR_TRNASVR_BE_ISOLATED;
+                    goto comfsm_action_4_keep_state;
+
+                default:
+                    break;
+            }
+            goto comfsm_action_4_unexpected;
+
+       default:
+           break;
+    }
+    goto comfsm_action_4_unexpected;
+
+
+comfsm_action_4_keep_state:
+    return return_val;
+
+comfsm_action_4_reinit_obj:
+    SWPS_DEBUG("FSM action: %s re-initial.\n", self->swp_name);
+    return_val = _transvr_init_handler(self);
+    goto comfsm_action_4_identify_event;
+
+comfsm_action_4_reload_obj:
+    SWPS_DEBUG("FSM action: %s reload.\n", self->swp_name);
+    self->type = new_type;
+    return_val = reload_transvr_obj(self, new_type);
+    goto comfsm_action_4_identify_event;
+
+comfsm_action_4_identify_event:
+    switch (return_val) {
+        case EVENT_TRANSVR_INIT_UP:
+        case EVENT_TRANSVR_TASK_DONE:
+            goto comfsm_action_4_connected;
+
+        case EVENT_TRANSVR_INIT_DOWN:
+            goto comfsm_action_4_disconnected;
+
+        case EVENT_TRANSVR_INIT_REINIT:
+            goto comfsm_action_4_nothing;
+
+        case EVENT_TRANSVR_TASK_WAIT:
+            self->state = STATE_TRANSVR_INIT;
+            return ERR_TRANSVR_TASK_BUSY;
+
+        case EVENT_TRANSVR_TASK_FAIL:
+            SWPS_INFO("%s detect EVENT_TRANSVR_TASK_FAIL.\n", self->swp_name);
+            goto comfsm_action_4_unexpected;
+
+        case EVENT_TRANSVR_INIT_FAIL:
+            SWPS_INFO("%s detect EVENT_TRANSVR_INIT_FAIL.\n", self->swp_name);
+            goto comfsm_action_4_unexpected;
+
+        case EVENT_TRANSVR_RELOAD_FAIL:
+            SWPS_INFO("%s detect EVENT_TRANSVR_RELOAD_FAIL.\n", self->swp_name);
+            goto comfsm_action_4_unexpected;
+
+        case EVENT_TRANSVR_I2C_CRASH:
+            goto comfsm_action_4_report_i2c_crash;
+
+        case EVENT_TRANSVR_EXCEP_ISOLATED:
+            goto comfsm_action_4_isolate_obj;
+
+        default:
+            SWPS_INFO("%s detect undefined event:%d.\n", self->swp_name, return_val);
+            goto comfsm_action_4_unexpected;
+    }
+
+comfsm_action_4_nothing:
+    SWPS_DEBUG("FSM action: %s do nothing.\n", self->swp_name);
+    return 0;
+
+comfsm_action_4_connected:
+    SWPS_DEBUG("FSM action: %s Connected.\n", self->swp_name);
+    self->state = STATE_TRANSVR_CONNECTED;
+    self->type  = new_type;
+    self->send_uevent(self, KOBJ_ADD);
+    _transvr_clean_retry(self);
+    return 0;
+
+comfsm_action_4_disconnected:
+    SWPS_DEBUG("FSM action: %s Disconnected. \n", self->swp_name);
+    self->state = STATE_TRANSVR_DISCONNECTED;
+    self->temp  = EVENT_TRANSVR_TASK_DONE;
+    self->send_uevent(self, KOBJ_REMOVE);
+    _transvr_clean_retry(self);
+    _transvr_clean_handler(self);
+    return ERR_TRANSVR_UNPLUGGED;
+
+comfsm_action_4_report_i2c_crash:
+    SWPS_DEBUG("FSM action: %s report I2C crash.\n", self->swp_name);
+    self->state = STATE_TRANSVR_UNEXCEPTED;
+    return ERR_TRANSVR_I2C_CRASH;
+
+comfsm_action_4_isolate_obj:
+    SWPS_DEBUG("FSM action: %s isolate.\n", self->swp_name);
+    self->state = STATE_TRANSVR_ISOLATED;
+    return ERR_TRNASVR_BE_ISOLATED;
+
+comfsm_action_4_unexpected:
+    SWPS_INFO("FSM action: %s unexpected.\n", self->swp_name);
+    SWPS_INFO("Dump: <os>:%d <ot>:0x%02x <ns>:%d <nt>:0x%02x\n",
+              old_state, old_type, new_state, new_type);
+    self->state = STATE_TRANSVR_UNEXCEPTED;
+    self->send_uevent(self, KOBJ_REMOVE);
+    _transvr_clean_handler(self);
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+int
+fake_fsm_4_direct_mode(struct transvr_obj_s* self,
+                       char *caller_name){
+    self->state = STATE_TRANSVR_CONNECTED;
+    self->type  = TRANSVR_TYPE_FAKE;
+    return 0;
+}
+
+
+int
+fake_fsm_4_polling_mode(struct transvr_obj_s* self,
+                        char *caller_name){
+    self->state = STATE_TRANSVR_CONNECTED;
+    self->type  = TRANSVR_TYPE_FAKE;
+    return 0;
+}
+
+
+/* ========== Object functions for Initial procedure ==========
+ */
+int
+transvr_init_common(struct transvr_obj_s *self){
+    /* Nothing to update */
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+transvr_init_fake(struct transvr_obj_s *self){
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+transvr_init_sfp(struct transvr_obj_s *self){
+
+    int  tmp_val  = DEBUG_TRANSVR_INT_VAL;
+    int  err_code = DEBUG_TRANSVR_INT_VAL;
+    char *err_msg = "ERR";
+
+    self->info = sft_detect_transvr_class(self);
+    /* Disable auto_config */
+    if (!self->auto_config) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    /* Handle multi-rate */
+    err_code = initfunc_sfp_handle_multi_rate_mode(self);
+    if (err_code < 0) {
+        err_msg = "initfunc_sfp_handle_multi_rate_mode fail!";
+        goto err_transvr_init_sfp_1;
+    }
+    /* Handle 1G- RJ45 */
+    tmp_val  = err_code;
+    err_code = initfunc_sfp_handle_1g_rj45(self);
+    if (err_code < 0) {
+        err_msg = "initfunc_sfp_handle_1g_rj45 fail!";
+        goto err_transvr_init_sfp_1;
+    }
+    tmp_val = (tmp_val > err_code ? tmp_val : err_code);
+    if (tmp_val > EVENT_TRANSVR_TASK_DONE) {
+        return tmp_val;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_transvr_init_sfp_1:
+    SWPS_INFO("%s: %s <err>:%d <port>:%s\n",
+              __func__, err_msg, err_code, self->swp_name);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+int
+transvr_init_qsfp(struct transvr_obj_s *self){
+
+    int  err = EVENT_TRANSVR_EXCEP_EXCEP;
+    char *emsg = "ERR";
+
+    self->info = qsft_detect_transvr_class(self);
+    if (!self->auto_config) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    err = initfunc_qsfp_handle_power_mode(self);
+    if (err < 0){
+        emsg = "initfunc_qsfp_handle_tx_disable fail!";
+        goto err_transvr_init_qsfp;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_transvr_init_qsfp:
+    SWPS_INFO("%s: %s <err>:%d <port>:%s\n",
+              __func__, emsg, err, self->swp_name);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+int
+transvr_init_qsfp28(struct transvr_obj_s *self){
+
+    int  tmp_val  = EVENT_TRANSVR_EXCEP_EXCEP;
+    int  err_val  = EVENT_TRANSVR_EXCEP_EXCEP;
+    char *err_msg = "ERR";
+
+    /* Handle QSFP common */
+    err_val = transvr_init_qsfp(self);
+    if (err_val < 0){
+        err_msg = "transvr_init_qsfp fail!";
+        goto err_transvr_init_qsfp28_1;
+    }
+    /* Disable auto_config */
+    if (!self->auto_config) {
+        return err_val;
+    }
+    /* Handle CDR */
+    tmp_val = err_val;
+    err_val = initfunc_qsfp28_handle_cdr(self);
+    if (err_val < 0){
+        err_msg = "Handle CDR fail!";
+        goto err_transvr_init_qsfp28_1;
+    }
+    tmp_val = (tmp_val > err_val ? tmp_val : err_val);
+    if (tmp_val > EVENT_TRANSVR_TASK_DONE) {
+        return tmp_val;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_transvr_init_qsfp28_1:
+    SWPS_INFO("%s: %s <err>:%d <port>:%s\n",
+              __func__, err_msg, err_val, self->swp_name);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+/* ========== Object Initial handler ==========
+ */
+static int
+_is_transvr_valid(struct transvr_obj_s *self,
+                  int type,
+                  int state) {
+    /* [Return]
+     *   0                        : OK, inserted
+     *   EVENT_TRANSVR_INIT_DOWN  : OK, removed
+     *   EVENT_TRANSVR_INIT_FAIL  : Outside error, type doesn't supported
+     *   EVENT_TRANSVR_EXCEP_INIT : Internal error, state undefined
+     */
+    switch (type) {
+        case TRANSVR_TYPE_SFP:
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+        case TRANSVR_TYPE_QSFP_28:
+        case TRANSVR_TYPE_UNPLUGGED:
+        case TRANSVR_TYPE_FAKE:
+            break;
+        default:
+            SWPS_INFO("detect undefined type:0x%02x on %s\n",
+                      type, self->swp_name);
+            return EVENT_TRANSVR_INIT_FAIL;
+    }
+    switch (state) {
+        case STATE_TRANSVR_DISCONNECTED:
+            return EVENT_TRANSVR_INIT_DOWN;
+        case STATE_TRANSVR_INIT:
+        case STATE_TRANSVR_CONNECTED:
+        case STATE_TRANSVR_SWAPPED:
+            break;
+        default:
+            SWPS_INFO("detect undefined state:%d on %s\n",
+                      state, self->swp_name);
+            return EVENT_TRANSVR_EXCEP_INIT;
+    }
+    return 0;
+}
+
+
+static int
+_is_transvr_hw_ready(struct transvr_obj_s *self,
+                     int type){
+    /* [Return]
+     *   EVENT_TRANSVR_TASK_DONE : Ready
+     *   EVENT_TRANSVR_TASK_WAIT : Not ready
+     *   EVENT_TRANSVR_INIT_FAIL : Error
+     */
+    int addr   = DEBUG_TRANSVR_INT_VAL;
+    int page   = DEBUG_TRANSVR_INT_VAL;
+    int offs   = DEBUG_TRANSVR_INT_VAL;
+    int bit    = DEBUG_TRANSVR_INT_VAL;
+    int ready  = DEBUG_TRANSVR_INT_VAL;
+    int err    = DEBUG_TRANSVR_INT_VAL;
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+    uint8_t ab_val = DEBUG_TRANSVR_HEX_VAL;
+
+    switch (type) {
+        case TRANSVR_TYPE_SFP:
+            addr   = VAL_TRANSVR_8472_READY_ADDR;
+            page   = VAL_TRANSVR_8472_READY_PAGE;
+            offs   = VAL_TRANSVR_8472_READY_OFFSET;
+            bit    = VAL_TRANSVR_8472_READY_BIT;
+            ready  = VAL_TRANSVR_8472_READY_VALUE;
+            ab_val = VAL_TRANSVR_8472_READY_ABNORMAL;
+            break;
+
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+        case TRANSVR_TYPE_QSFP_28:
+            addr   = VAL_TRANSVR_8436_READY_ADDR;
+            page   = VAL_TRANSVR_8436_READY_PAGE;
+            offs   = VAL_TRANSVR_8436_READY_OFFSET;
+            bit    = VAL_TRANSVR_8436_READY_BIT;
+            ready  = VAL_TRANSVR_8436_READY_VALUE;
+            ab_val = VAL_TRANSVR_8436_READY_ABNORMAL;
+            break;
+
+        case TRANSVR_TYPE_UNPLUGGED:
+        case TRANSVR_TYPE_FAKE:
+            return EVENT_TRANSVR_TASK_DONE;
+
+        default:
+            emsg = "unexpected case";
+            goto err_is_transvr_hw_ready;
+    }
+    /* Select target page */
+    err = _common_setup_page(self, addr, page, offs, 1, 0);
+    if (err < 0) {
+        emsg = "setup page fail";
+        goto err_is_transvr_hw_ready;
+    }
+    /* Check feature supported
+     * [Note]
+     *   Some of transceiver/cables doesn't support "Status Indicators"
+     *   (ex:DAC, RJ45 copper SFP ...etc). In these case, we bypass the
+     *   step of checking Status Indicators, then state machine will take
+     *   the following handle procedure.
+     */
+    err = i2c_smbus_read_byte_data(self->i2c_client_p,
+                                   VAL_TRANSVR_COMID_OFFSET);
+    if (err < 0) {
+        emsg = "doesn't support Status Indicators";
+        goto bypass_is_transvr_hw_ready;
+    }
+    /* Filter abnormal case */
+    if (err == ab_val) {
+        emsg = "detect using unusual definition.";
+        goto bypass_is_transvr_hw_ready;
+    }
+    /* Get Status Indicators */
+    err = i2c_smbus_read_byte_data(self->i2c_client_p, offs);
+    if (err < 0) {
+        emsg = "detect current value fail";
+        goto err_is_transvr_hw_ready;
+    }
+    if ((err & (1<<bit)) == ready) {
+        return EVENT_TRANSVR_TASK_DONE;
+    }
+    return EVENT_TRANSVR_TASK_WAIT;
+
+bypass_is_transvr_hw_ready:
+    SWPS_DEBUG("%s: %s <type>:%d\n", __func__, emsg, type);
+    return EVENT_TRANSVR_TASK_DONE;
+
+err_is_transvr_hw_ready:
+    SWPS_DEBUG("%s: %s <type>:%d\n", __func__, emsg, type);
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+static int
+_is_transvr_support_ctle(struct transvr_obj_s *self) {
+
+    switch (self->info) {
+        case TRANSVR_CLASS_OPTICAL_25G:
+        case TRANSVR_CLASS_OPTICAL_25G_AOC:
+        case TRANSVR_CLASS_OPTICAL_25G_SR:
+        case TRANSVR_CLASS_OPTICAL_25G_LR:
+        case TRANSVR_CLASS_OPTICAL_25G_ER:
+        case TRANSVR_CLASS_OPTICAL_100G:
+        case TRANSVR_CLASS_OPTICAL_100G_AOC:
+        case TRANSVR_CLASS_OPTICAL_100G_SR4:
+        case TRANSVR_CLASS_OPTICAL_100G_LR4:
+        case TRANSVR_CLASS_OPTICAL_100G_ER4:
+        case TRANSVR_CLASS_OPTICAL_100G_PSM4:
+            return 1;
+        default:
+            break;
+    }
+    return 0;
+}
+
+
+static int
+_transvr_init_handler(struct transvr_obj_s *self){
+
+    int detect[2];
+    int d_state   = STATE_TRANSVR_UNEXCEPTED;
+    int d_type    = TRANSVR_TYPE_ERROR;
+    int result    = ERR_TRANSVR_UNINIT;
+    int retry     = 6;  /* (6+1) x 0.3 = 2.1s > spec:2.0s */
+    int elimit    = 63;
+    char emsg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    /* Clean and check callback */
+    self->state = STATE_TRANSVR_INIT;
+    if (self->init == NULL) {
+        snprintf(emsg, elimit, "init() is null");
+        goto initer_err_case_unexcept_0;
+    }
+    if (self->clean == NULL) {
+        snprintf(emsg, elimit, "clean() is null");
+        goto initer_err_case_unexcept_0;
+    }
+    self->clean(self);
+
+    /* Detect transceiver information */
+    result = detect_transvr_state(self, detect);
+    if (result < 0) {
+        snprintf(emsg, elimit, "detect_transvr_state() fail");
+        switch (result) {
+            case ERR_TRANSVR_I2C_CRASH:
+                goto initer_err_case_i2c_ceash;
+            case ERR_TRNASVR_BE_ISOLATED:
+                goto initer_err_case_be_isolated;
+
+            case ERR_TRANSVR_UNEXCPT:
+            default:
+                break;
+        }
+        goto initer_err_case_retry_1;
+    }
+    d_state = detect[0];
+    d_type  = detect[1];
+
+    /* Verify transceiver type and state */
+    switch (_is_transvr_valid(self, d_type, d_state)) {
+        case 0:
+            break;
+        case EVENT_TRANSVR_INIT_DOWN:
+            goto initer_ok_case_down;;
+        case EVENT_TRANSVR_INIT_FAIL:
+            snprintf(emsg, elimit, "transceiver type doesn't support");
+            goto initer_err_case_alarm_to_user;
+        case EVENT_TRANSVR_EXCEP_INIT:
+        default:
+            goto initer_err_case_unexcept_1;
+    }
+
+    /* Handle reload case */
+    if (self->type != d_type){
+        /* This is the protect mechanism. Normally, This case will not happen.
+         * When State machine detect swap event during initial, It will trigger
+         * reload function to ensure type correct. */
+        if (_reload_transvr_obj(self, d_type) < 0){
+            snprintf(emsg, elimit, "reload object fail");
+            goto initer_err_case_unexcept_1;
+        }
+    }
+
+    /* Check transceiver HW initial ready */
+    switch (_is_transvr_hw_ready(self, d_type)) {
+        case EVENT_TRANSVR_TASK_DONE:
+            break;
+        case EVENT_TRANSVR_TASK_WAIT:
+            goto initer_err_case_retry_1;
+        case EVENT_TRANSVR_INIT_FAIL:
+        default:
+            goto initer_err_case_unexcept_1;
+    }
+
+    /* Try to update all and check */
+    if (self->update_all(self, 1) < 0){
+        /* For some transceiver, EEPROME has lag issues during initial stage.
+         * In this case, we set status back to STATE_TRANSVR_NEW, than it will
+         * be checked in next polling cycle. */
+        goto initer_err_case_retry_1;
+    }
+
+    /* Execute init() call back */
+    result = self->init(self);
+    switch (result) {
+        case EVENT_TRANSVR_TASK_DONE:
+            break;
+        case EVENT_TRANSVR_TASK_WAIT:
+            goto initer_ok_case_wait;
+
+        default:
+            snprintf(emsg, elimit, "undefined init() return:%d\n", result);
+            goto initer_err_case_unexcept_1;
+    }
+    goto initer_ok_case_up;
+
+
+initer_ok_case_wait:
+    self->dump_all(self);
+    return EVENT_TRANSVR_TASK_WAIT;
+
+initer_ok_case_up:
+    self->state = STATE_TRANSVR_CONNECTED;
+    self->temp  = 0;
+    self->dump_all(self);
+    return EVENT_TRANSVR_INIT_UP;
+
+initer_ok_case_down:
+    self->temp  = 0;
+    self->state = STATE_TRANSVR_DISCONNECTED;
+    return EVENT_TRANSVR_INIT_DOWN;
+
+initer_err_case_i2c_ceash:
+    SWPS_DEBUG("%s: %s <port>:%s <case>:I2C crash\n",
+               __func__, emsg, self->swp_name);
+    self->state = STATE_TRANSVR_UNEXCEPTED;
+    return EVENT_TRANSVR_I2C_CRASH;
+
+initer_err_case_be_isolated:
+    SWPS_DEBUG("%s: %s <port>:%s <case>:isolated\n",
+               __func__, emsg, self->swp_name);
+    self->state = STATE_TRANSVR_ISOLATED;
+    return EVENT_TRANSVR_EXCEP_ISOLATED;
+
+initer_err_case_retry_1:
+    SWPS_DEBUG("%s: %s <port>:%s <case>:retry\n",
+               __func__, emsg, self->swp_name);
+    if (_transvr_handle_retry(self, retry) == 0) {
+        self->state = STATE_TRANSVR_NEW;
+        return EVENT_TRANSVR_INIT_REINIT;
+    }
+    goto initer_err_case_alarm_to_user;
+
+initer_err_case_unexcept_1:
+    self->clean(self);
+initer_err_case_unexcept_0:
+    self->state = STATE_TRANSVR_UNEXCEPTED;
+    if (_is_except_happened_4_pmode(self, d_state) &&
+        (self->mode == TRANSVR_MODE_POLLING) ){
+        SWPS_INFO("%s: %s <port>:%s\n", __func__, emsg, self->swp_name);
+        SWPS_INFO("Dump: <os>:%d <ot>:%d <ns>:%d <nt>:%d\n",
+                   self->state, self->type, d_state, d_type);
+    }
+    return EVENT_TRANSVR_INIT_FAIL;
+
+initer_err_case_alarm_to_user:
+    SWPS_DEBUG("%s: %s <port>:%s <case>:alarm_to_user\n",
+               __func__, emsg, self->swp_name);
+    self->state = STATE_TRANSVR_UNEXCEPTED;
+    alarm_msg_2_user(self, "detected transceiver/cables not meet SFF standard");
+    return EVENT_TRANSVR_INIT_FAIL;
+}
+
+
+/* ========== Object functions for Clean procedure ==========
+ */
+int
+_transvr_clean_handler(struct transvr_obj_s *self){
+
+    int retval = DEBUG_TRANSVR_INT_VAL;
+
+    if (!self->clean) {
+        SWPS_ERR("%s: %s clean() is NULL.\n",
+                __func__, self->swp_name);
+        return EVENT_TRANSVR_TASK_FAIL;
+    }
+    retval = self->clean(self);
+    if (retval != EVENT_TRANSVR_TASK_DONE){
+        SWPS_ERR("%s: %s clean() fail. [ERR]:%d\n",
+                __func__, self->swp_name, retval);
+        return retval;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+common_transvr_clean(struct transvr_obj_s *self){
+
+    transvr_task_free_all(self);
+    transvr_cache_free_all(self);
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+qsfp_transvr_clean(struct transvr_obj_s *self){
+
+    int retval;
+    int lpower_config = 1;
+
+    retval = _taskfunc_qsfp_setup_power_mod(self, lpower_config);
+    if (retval < 0){
+        SWPS_ERR("%s: Set lpmod fail! <err>:%d\n",
+                __func__, retval);
+        return retval;
+    }
+    retval = common_transvr_clean(self);
+    if (retval < 0){
+        SWPS_ERR("%s: common_transvr_clean fail! <err>:%d\n",
+                __func__, retval);
+        return retval;
+    }
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+int
+fake_transvr_clean(struct transvr_obj_s *self){
+
+    return EVENT_TRANSVR_TASK_DONE;
+}
+
+
+/* ========== Object functions for check and update ==========
+ */
+int
+common_transvr_check(struct transvr_obj_s *self){
+
+    char fun_str[32]  = "common_transvr_check";
+
+    if (self->mode != TRANSVR_MODE_POLLING) {
+        SWPS_ERR("%s: mode:%d is not TRANSVR_MODE_POLLING\n",
+                fun_str, self->mode);
+        return ERR_TRANSVR_UNEXCPT;
+    }
+    /* Trigger delay task */
+    transvr_task_run_all(self);
+    /* Trigger state machine to check and update */
+    return self->fsm_4_polling(self, fun_str);
+}
+
+
+int
+fake_transvr_check(struct transvr_obj_s *self){
+    return 0;
+}
+
+
+/* ========== Functions for Factory pattern ==========
+ */
+static int
+setup_transvr_public_cb(struct transvr_obj_s *self,
+                        int transvr_type){
+    switch (transvr_type){
+        case TRANSVR_TYPE_SFP:
+            self->get_id              = common_get_id;
+            self->get_ext_id          = common_get_ext_id;
+            self->get_connector       = common_get_connector;
+            self->get_vendor_name     = common_get_vendor_name;
+            self->get_vendor_pn       = common_get_vendor_pn;
+            self->get_vendor_rev      = common_get_vendor_rev;
+            self->get_vendor_sn       = common_get_vendor_sn;
+            self->get_power_cls       = unsupported_get_func;
+            self->get_br              = common_get_br;
+            self->get_len_sm          = sfp_get_len_sm;
+            self->get_len_smf         = common_get_len_smf;
+            self->get_len_om1         = common_get_len_om1;
+            self->get_len_om2         = common_get_len_om2;
+            self->get_len_om3         = common_get_len_om3;
+            self->get_len_om4         = common_get_len_om4;
+            self->get_comp_rev        = common_get_comp_rev;
+            self->get_comp_eth_1      = sfp_get_comp_eth_1;
+            self->get_comp_eth_10     = sfp_get_comp_eth_10;
+            self->get_comp_eth_10_40  = unsupported_get_func;
+            self->get_comp_extend     = common_get_comp_extended;
+            self->get_cdr             = unsupported_get_func;
+            self->get_rate_id         = sfp_get_rate_id;
+            self->get_soft_rs0        = sfp_get_soft_rs0;
+            self->get_soft_rs1        = sfp_get_soft_rs1;
+            self->get_info            = common_get_info;
+            self->get_if_type         = sfp_get_if_type;
+            self->get_if_speed        = sfp_get_if_speed;
+            self->get_if_lane         = common_get_if_lane;
+            self->get_curr_temp       = sfp_get_transvr_temp;
+            self->get_curr_vol        = sfp_get_transvr_voltage;
+            self->get_soft_rx_los     = unsupported_get_func2;
+            self->get_soft_tx_disable = unsupported_get_func2;
+            self->get_soft_tx_fault   = unsupported_get_func2;
+            self->get_auto_tx_disable = unsupported_get_func2;
+            self->get_tx_bias         = sfp_get_transvr_tx_bias;
+            self->get_tx_power        = sfp_get_transvr_tx_power;
+            self->get_rx_power        = sfp_get_transvr_rx_power;
+            self->get_tx_eq           = sfp_get_transvr_tx_eq;
+            self->get_rx_am           = unsupported_get_func2;
+            self->get_rx_em           = sfp_get_transvr_rx_em;
+            self->get_wavelength      = sfp_get_wavelength;
+            self->get_extphy_offset   = sfp_get_1g_rj45_extphy_offset;
+            self->get_extphy_reg      = sfp_get_1g_rj45_extphy_reg;
+            self->set_cdr             = unsupported_set_func;
+            self->set_soft_rs0        = sfp_set_soft_rs0;
+            self->set_soft_rs1        = sfp_set_soft_rs1;
+            self->set_soft_tx_disable = unsupported_set_func;
+            self->set_auto_tx_disable = unsupported_set_func;
+            self->set_tx_eq           = sfp_set_tx_eq;
+            self->set_rx_am           = unsupported_set_func;
+            self->set_rx_em           = sfp_set_rx_em;
+            self->set_extphy_offset   = sfp_set_1g_rj45_extphy_offset;
+            self->set_extphy_reg      = sfp_set_1g_rj45_extphy_reg;
+            return 0;
+
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+            self->get_id              = common_get_id;
+            self->get_ext_id          = common_get_ext_id;
+            self->get_connector       = common_get_connector;
+            self->get_vendor_name     = common_get_vendor_name;
+            self->get_vendor_pn       = common_get_vendor_pn;
+            self->get_vendor_rev      = common_get_vendor_rev;
+            self->get_vendor_sn       = common_get_vendor_sn;
+            self->get_power_cls       = qsfp_get_power_cls;
+            self->get_br              = common_get_br;
+            self->get_len_sm          = unsupported_get_func;
+            self->get_len_smf         = common_get_len_smf;
+            self->get_len_om1         = common_get_len_om1;
+            self->get_len_om2         = common_get_len_om2;
+            self->get_len_om3         = common_get_len_om3;
+            self->get_len_om4         = common_get_len_om4;
+            self->get_comp_rev        = common_get_comp_rev;
+            self->get_comp_eth_1      = qsfp_get_comp_eth;
+            self->get_comp_eth_10     = unsupported_get_func;
+            self->get_comp_eth_10_40  = qsfp_get_comp_10_40;
+            self->get_comp_extend     = common_get_comp_extended;
+            self->get_cdr             = unsupported_get_func;
+            self->get_rate_id         = unsupported_get_func;
+            self->get_soft_rs0        = unsupported_get_func; /* TBD */
+            self->get_soft_rs1        = unsupported_get_func; /* TBD */
+            self->get_info            = common_get_info;
+            self->get_if_type         = qsfp_get_if_type;
+            self->get_if_speed        = qsfp_get_if_speed;
+            self->get_if_lane         = common_get_if_lane;
+            self->get_curr_temp       = qsfp_get_transvr_temp;
+            self->get_curr_vol        = qsfp_get_transvr_voltage;
+            self->get_soft_rx_los     = qsfp_get_soft_rx_los;
+            self->get_soft_tx_disable = qsfp_get_soft_tx_disable;
+            self->get_soft_tx_fault   = qsfp_get_soft_tx_fault;
+            self->get_auto_tx_disable = qsfp_get_auto_tx_disable;
+            self->get_tx_bias         = qsfp_get_transvr_tx_bias;
+            self->get_tx_power        = qsfp_get_transvr_tx_power;
+            self->get_rx_power        = qsfp_get_transvr_rx_power;
+            self->get_tx_eq           = unsupported_get_func2;
+            self->get_rx_am           = unsupported_get_func2;
+            self->get_rx_em           = unsupported_get_func2;
+            self->get_wavelength      = qsfp_get_wavelength;
+            self->get_extphy_offset   = unsupported_get_func2;
+            self->get_extphy_reg      = unsupported_get_func2;
+            self->set_cdr             = unsupported_set_func;
+            self->set_soft_rs0        = unsupported_set_func; /* TBD */
+            self->set_soft_rs1        = unsupported_set_func; /* TBD */
+            self->set_soft_tx_disable = qsfp_set_soft_tx_disable;
+            self->set_auto_tx_disable = qsfp_set_auto_tx_disable;
+            self->set_tx_eq           = unsupported_set_func;
+            self->set_rx_am           = unsupported_set_func;
+            self->set_rx_em           = unsupported_set_func;
+            self->set_extphy_offset   = unsupported_set_func;
+            self->set_extphy_reg      = unsupported_set_func;
+            return 0;
+
+        case TRANSVR_TYPE_QSFP_28:
+            self->get_id              = common_get_id;
+            self->get_ext_id          = common_get_ext_id;
+            self->get_connector       = common_get_connector;
+            self->get_vendor_name     = common_get_vendor_name;
+            self->get_vendor_pn       = common_get_vendor_pn;
+            self->get_vendor_rev      = common_get_vendor_rev;
+            self->get_vendor_sn       = common_get_vendor_sn;
+            self->get_power_cls       = qsfp_get_power_cls;
+            self->get_br              = common_get_br;
+            self->get_len_sm          = unsupported_get_func;
+            self->get_len_smf         = common_get_len_smf;
+            self->get_len_om1         = common_get_len_om1;
+            self->get_len_om2         = common_get_len_om2;
+            self->get_len_om3         = common_get_len_om3;
+            self->get_len_om4         = common_get_len_om4;
+            self->get_comp_rev        = common_get_comp_rev;
+            self->get_comp_eth_1      = qsfp_get_comp_eth;
+            self->get_comp_eth_10     = unsupported_get_func;
+            self->get_comp_eth_10_40  = qsfp_get_comp_10_40;
+            self->get_comp_extend     = common_get_comp_extended;
+            self->get_cdr             = qsfp_get_cdr;
+            self->get_rate_id         = unsupported_get_func;
+            self->get_soft_rs0        = unsupported_get_func; /* TBD */
+            self->get_soft_rs1        = unsupported_get_func; /* TBD */
+            self->get_info            = common_get_info;
+            self->get_if_type         = qsfp_get_if_type;
+            self->get_if_speed        = qsfp_get_if_speed;
+            self->get_if_lane         = common_get_if_lane;
+            self->get_curr_temp       = qsfp_get_transvr_temp;
+            self->get_curr_vol        = qsfp_get_transvr_voltage;
+            self->get_soft_rx_los     = qsfp_get_soft_rx_los;
+            self->get_soft_tx_disable = qsfp_get_soft_tx_disable;
+            self->get_soft_tx_fault   = qsfp_get_soft_tx_fault;
+            self->get_auto_tx_disable = qsfp_get_auto_tx_disable;
+            self->get_tx_bias         = qsfp_get_transvr_tx_bias;
+            self->get_tx_power        = qsfp_get_transvr_tx_power;
+            self->get_rx_power        = qsfp_get_transvr_rx_power;
+            self->get_tx_eq           = qsfp_get_transvr_tx_eq;
+            self->get_rx_am           = qsfp_get_transvr_rx_am;
+            self->get_rx_em           = qsfp_get_transvr_rx_em;
+            self->get_wavelength      = qsfp_get_wavelength;
+            self->get_extphy_offset   = unsupported_get_func2;
+            self->get_extphy_reg      = unsupported_get_func2;
+            self->set_cdr             = qsfp_set_cdr;
+            self->set_soft_rs0        = unsupported_set_func; /* TBD */
+            self->set_soft_rs1        = unsupported_set_func; /* TBD */
+            self->set_soft_tx_disable = qsfp_set_soft_tx_disable;
+            self->set_auto_tx_disable = qsfp_set_auto_tx_disable;
+            self->set_tx_eq           = qsfp_set_tx_eq;
+            self->set_rx_am           = qsfp_set_rx_am;
+            self->set_rx_em           = qsfp_set_rx_em;
+            self->set_extphy_offset   = unsupported_set_func;
+            self->set_extphy_reg      = unsupported_set_func;
+            return 0;
+
+        case TRANSVR_TYPE_FAKE:
+            self->get_id              = fake_get_hex;
+            self->get_ext_id          = fake_get_hex;
+            self->get_connector       = fake_get_hex;
+            self->get_vendor_name     = fake_get_str;
+            self->get_vendor_pn       = fake_get_str;
+            self->get_vendor_rev      = fake_get_str;
+            self->get_vendor_sn       = fake_get_str;
+            self->get_power_cls       = fake_get_int;
+            self->get_br              = fake_get_hex;
+            self->get_len_sm          = fake_get_int;
+            self->get_len_smf         = fake_get_int;
+            self->get_len_om1         = fake_get_int;
+            self->get_len_om2         = fake_get_int;
+            self->get_len_om3         = fake_get_int;
+            self->get_len_om4         = fake_get_int;
+            self->get_comp_rev        = fake_get_hex;
+            self->get_comp_eth_1      = fake_get_hex;
+            self->get_comp_eth_10     = fake_get_hex;
+            self->get_comp_eth_10_40  = fake_get_hex;
+            self->get_comp_extend     = fake_get_hex;
+            self->get_cdr             = fake_get_hex;
+            self->get_rate_id         = fake_get_hex;
+            self->get_soft_rs0        = fake_get_binary;
+            self->get_soft_rs1        = fake_get_binary;
+            self->get_info            = fake_get_int;
+            self->get_if_type         = fake_get_str;
+            self->get_if_speed        = fake_get_str;
+            self->get_if_lane         = fake_get_str;
+            self->get_curr_temp       = fake_get_str;
+            self->get_curr_vol        = fake_get_str;
+            self->get_soft_rx_los     = fake_get_str;
+            self->get_soft_tx_disable = fake_get_str;
+            self->get_soft_tx_fault   = fake_get_str;
+            self->get_auto_tx_disable = fake_get_str;
+            self->get_tx_bias         = fake_get_str;
+            self->get_tx_power        = fake_get_str;
+            self->get_rx_power        = fake_get_str;
+            self->get_tx_eq           = fake_get_str;
+            self->get_rx_am           = fake_get_str;
+            self->get_rx_em           = fake_get_str;
+            self->get_wavelength      = fake_get_str;
+            self->get_extphy_offset   = fake_get_str;
+            self->get_extphy_reg      = fake_get_str;
+            self->set_cdr             = fake_set_hex;
+            self->set_soft_rs0        = fake_set_int;
+            self->set_soft_rs1        = fake_set_int;
+            self->set_soft_tx_disable = fake_set_int;
+            self->set_auto_tx_disable = fake_set_int;
+            self->set_tx_eq           = fake_set_int;
+            self->set_rx_am           = fake_set_int;
+            self->set_rx_em           = fake_set_int;
+            self->set_extphy_offset   = fake_set_hex;
+            self->set_extphy_reg      = fake_set_hex;
+            return 0;
+
+        default:
+            break;
+    }
+    SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type);
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+static int
+setup_transvr_private_cb(struct transvr_obj_s *self,
+                         int transvr_type){
+    switch (transvr_type){
+        case TRANSVR_TYPE_SFP:
+            self->init  = transvr_init_sfp;
+            self->clean = common_transvr_clean;
+            self->check = common_transvr_check;
+            self->update_all = _sfp_update_attr_all;
+            self->fsm_4_direct = common_fsm_4_direct_mode;
+            self->fsm_4_polling = common_fsm_4_polling_mode;
+            self->send_uevent = sfp_send_uevent;
+            self->dump_all = sfp_transvr_dump;
+            return 0;
+
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+            self->init  = transvr_init_qsfp;
+            self->clean = qsfp_transvr_clean;
+            self->check = common_transvr_check;
+            self->update_all = _qsfp_update_attr_all;
+            self->fsm_4_direct = common_fsm_4_direct_mode;
+            self->fsm_4_polling = common_fsm_4_polling_mode;
+            self->send_uevent = qsfp_send_uevent;
+            self->dump_all = qsfp_transvr_dump;
+            return 0;
+
+        case TRANSVR_TYPE_QSFP_28:
+            self->init  = transvr_init_qsfp28;
+            self->clean = qsfp_transvr_clean;
+            self->check = common_transvr_check;
+            self->update_all = _qsfp_update_attr_all;
+            self->fsm_4_direct = common_fsm_4_direct_mode;
+            self->fsm_4_polling = common_fsm_4_polling_mode;
+            self->send_uevent = qsfp_send_uevent;
+            self->dump_all = qsfp_transvr_dump;
+            return 0;
+
+        case TRANSVR_TYPE_FAKE:
+            self->init  = transvr_init_fake;
+            self->clean = fake_transvr_clean;
+            self->check = fake_transvr_check;
+            self->update_all = fake_transvr_update;
+            self->fsm_4_direct = fake_fsm_4_direct_mode;
+            self->fsm_4_polling = fake_fsm_4_polling_mode;
+            self->send_uevent = fake_send_uevent;
+            self->dump_all = fake_transvr_dump;
+            return 0;
+
+        default:
+            break;
+    }
+    SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type);
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+static struct eeprom_map_s *
+get_eeprom_map(int transvr_type){
+
+    switch (transvr_type){
+        case TRANSVR_TYPE_SFP:
+            return &eeprom_map_sfp;
+        case TRANSVR_TYPE_QSFP:
+        case TRANSVR_TYPE_QSFP_PLUS:
+            return &eeprom_map_qsfp;
+        case TRANSVR_TYPE_QSFP_28:
+            return &eeprom_map_qsfp28;
+
+        default:
+            break;
+    }
+    SWPS_WARN("%s: Detect non-defined type:%d\n", __func__, transvr_type);
+    return NULL;
+}
+
+
+static int
+setup_transvr_ssize_attr(char *swp_name,
+                         struct transvr_obj_s *self,
+                         struct eeprom_map_s  *map_p,
+                         struct ioexp_obj_s   *ioexp_obj_p,
+                         int ioexp_virt_offset,
+                         int transvr_type,
+                         int chipset_type,
+                         int chan_id,
+                         int run_mode){
+    switch (run_mode){
+        case TRANSVR_MODE_DIRECT:  /* Direct access device mode */
+        case TRANSVR_MODE_POLLING: /* Polling mode, read from cache */
+            self->mode = run_mode;
+            break;
+        default:
+            SWPS_ERR("%s: non-defined run_mode:%d\n",
+                    __func__, run_mode);
+            self->mode = DEBUG_TRANSVR_INT_VAL;
+            return -1;
+    }
+    self->eeprom_map_p      = map_p;
+    self->ioexp_obj_p       = ioexp_obj_p;
+    self->ioexp_virt_offset = ioexp_virt_offset;
+    self->chan_id           = chan_id;
+    self->layout            = transvr_type;
+    self->type              = transvr_type;
+    self->chipset_type      = chipset_type;
+    self->state             = STATE_TRANSVR_NEW;
+    self->info              = STATE_TRANSVR_NEW;
+    self->auto_tx_disable   = VAL_TRANSVR_FUNCTION_DISABLE;
+    strncpy(self->swp_name, swp_name, 32);
+    mutex_init(&self->lock);
+    return 0;
+}
+
+
+static int
+setup_transvr_dsize_attr(struct transvr_obj_s *self){
+
+    char *emsg = DEBUG_TRANSVR_STR_VAL;
+
+    self->vendor_name = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL);
+    if (!self->vendor_name){
+        emsg = "vendor_name";
+        goto err_setup_d_attr;
+    }
+    self->vendor_pn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL);
+    if (!self->vendor_pn){
+        emsg = "vendor_pn";
+        goto err_setup_d_attr;
+    }
+    self->vendor_rev = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL);
+    if (!self->vendor_rev){
+        emsg = "vendor_rev";
+        goto err_setup_d_attr;
+    }
+    self->vendor_sn = kzalloc((LEN_TRANSVR_M_STR * sizeof(char)), GFP_KERNEL);
+    if (!self->vendor_sn){
+        emsg = "vendor_sn";
+        goto err_setup_d_attr;
+    }
+    self->worker_p = NULL;
+    return 0;
+
+err_setup_d_attr:
+    SWPS_ERR("%s: %s kzalloc fail!", __func__, emsg);
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+static int
+setup_i2c_client(struct transvr_obj_s *self){
+
+    struct i2c_adapter *adap  = NULL;
+    struct i2c_client *client = NULL;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    adap = i2c_get_adapter(self->chan_id);
+    if(!adap){
+        snprintf(err_msg, sizeof(err_msg),
+                "can not get adap:%d", self->chan_id);
+        goto err_setup_i2c_client;
+    }
+    client = kzalloc(sizeof(*client), GFP_KERNEL);
+    if (!client){
+        snprintf(err_msg, sizeof(err_msg),
+                "can not kzalloc client:%d", self->chan_id);
+        goto err_setup_i2c_client;
+    }
+    client->adapter = adap;
+    self->i2c_client_p = client;
+    self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS;
+    return 0;
+
+err_setup_i2c_client:
+    SWPS_ERR("%s: %s\n", __func__, err_msg);
+    return ERR_TRANSVR_UNEXCPT;
+}
+
+
+struct transvr_obj_s *
+create_transvr_obj(char *swp_name,
+                   int chan_id,
+                   struct ioexp_obj_s *ioexp_obj_p,
+                   int ioexp_virt_offset,
+                   int transvr_type,
+                   int chipset_type,
+                   int run_mode){
+
+    struct transvr_obj_s *result_p;
+    struct eeprom_map_s  *map_p;
+    char err_msg[64] = DEBUG_TRANSVR_STR_VAL;
+
+    /* Allocate transceiver object */
+    map_p = get_eeprom_map(transvr_type);
+    if (!map_p){
+        snprintf(err_msg, sizeof(err_msg),
+                "Invalid transvr_type:%d", transvr_type);
+        goto err_create_transvr_fail;
+    }
+    result_p = kzalloc(sizeof(*result_p), GFP_KERNEL);
+    if (!result_p){
+        snprintf(err_msg, sizeof(err_msg), "kzalloc fail");
+        goto err_create_transvr_fail;
+    }
+    /* Prepare static size attributes */
+    if (setup_transvr_ssize_attr(swp_name,
+                                 result_p,
+                                 map_p,
+                                 ioexp_obj_p,
+                                 ioexp_virt_offset,
+                                 transvr_type,
+                                 chipset_type,
+                                 chan_id,
+                                 run_mode) < 0){
+        goto err_create_transvr_sattr_fail;
+    }
+    /* Prepare dynamic size attributes */
+    if (setup_transvr_dsize_attr(result_p) < 0){
+        goto err_create_transvr_dattr_fail;
+    }
+    /* Prepare call back functions of object */
+    if (setup_transvr_public_cb(result_p, transvr_type) < 0){
+        goto err_create_transvr_dattr_fail;
+    }
+    /* Prepare call back functions of object */
+    if (setup_transvr_private_cb(result_p, transvr_type) < 0){
+        goto err_create_transvr_dattr_fail;
+    }
+    /* Prepare i2c client object */
+    if (setup_i2c_client(result_p) < 0){
+        goto err_create_transvr_dattr_fail;
+    }
+    return result_p;
+
+err_create_transvr_dattr_fail:
+    kfree(result_p->vendor_sn);
+    kfree(result_p->vendor_rev);
+    kfree(result_p->vendor_pn);
+    kfree(result_p->vendor_name);
+err_create_transvr_sattr_fail:
+    kfree(result_p);
+err_create_transvr_fail:
+    SWPS_ERR("%s: %s <chan>:%d <voff>:%d <type>:%d\n",
+            __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type);
+    return NULL;
+}
+
+
+static int
+_reload_transvr_obj(struct transvr_obj_s *self,
+                    int new_type){
+
+    struct eeprom_map_s *new_map_p;
+    struct eeprom_map_s *old_map_p = self->eeprom_map_p;
+    struct i2c_client   *old_i2c_p = self->i2c_client_p;
+    int old_type = self->type;
+
+    /* Change state to STATE_TRANSVR_INIT */
+    self->state = STATE_TRANSVR_INIT;
+    self->type  = new_type;
+    /* Replace EEPROME map */
+    new_map_p = get_eeprom_map(new_type);
+    if (!new_map_p){
+        goto err_private_reload_func_1;
+    }
+    self->eeprom_map_p = new_map_p;
+    /* Reload i2c client */
+    if (setup_i2c_client(self) < 0){
+        goto err_private_reload_func_2;
+    }
+    /* Replace call back functions */
+    if (setup_transvr_public_cb(self, new_type) < 0){
+        goto err_private_reload_func_3;
+    }
+    if (setup_transvr_private_cb(self, new_type) < 0){
+        goto err_private_reload_func_3;
+    }
+    kfree(old_i2c_p);
+    return 0;
+
+err_private_reload_func_3:
+    SWPS_INFO("%s: init() fail!\n", __func__);
+    kfree(old_i2c_p);
+    self->state = STATE_TRANSVR_UNEXCEPTED;
+    self->type  = TRANSVR_TYPE_ERROR;
+    return -2;
+
+err_private_reload_func_2:
+    self->eeprom_map_p = old_map_p;
+    self->i2c_client_p = old_i2c_p;
+err_private_reload_func_1:
+    self->state = STATE_TRANSVR_UNEXCEPTED;
+    self->type  = old_type;
+    SWPS_INFO("%s fail! <type>:0x%02x\n", __func__, new_type);
+    return -1;
+}
+
+
+static int
+reload_transvr_obj(struct transvr_obj_s *self,
+                   int new_type){
+
+    int result_val = ERR_TRANSVR_UNEXCPT;
+
+    /* Reload phase */
+    result_val = _reload_transvr_obj(self, new_type);
+    if (result_val < 0){
+        SWPS_INFO("%s: reload phase fail! <err>:%d\n",
+                  __func__, result_val);
+        return EVENT_TRANSVR_RELOAD_FAIL;
+    }
+    /* Initial phase */
+    result_val = _transvr_init_handler(self);
+    if (result_val < 0){
+        SWPS_INFO("%s: initial phase fail! <err>:%d\n",
+                  __func__, result_val);
+    }
+    return result_val;
+}
+
+
+int
+isolate_transvr_obj(struct transvr_obj_s *self) {
+
+    self->state = STATE_TRANSVR_ISOLATED;
+    SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name);
+    return 0;
+}
+
+
+int
+resync_channel_tier_2(struct transvr_obj_s *self) {
+
+    int val = TRANSVR_TYPE_ERROR;
+
+    if (self->state == STATE_TRANSVR_ISOLATED) {
+        return 0;
+    }
+    self->i2c_client_p->addr = VAL_TRANSVR_COMID_ARREESS;
+    val = i2c_smbus_read_byte_data(self->i2c_client_p,
+                                   VAL_TRANSVR_COMID_OFFSET);
+    if (val < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+
+/* -----------------------------------------
+ *   ToDo List
+ * -----------------------------------------
+ * 1. _sfp_detect_class_by_feature()
+ *    => Need check ACC use case.
+ * 2. _sfp_detect_class_by_1g_ethernet()
+ *    => Need check 0.1G use case.
+ * 3. Loopback transceiver use case.
+ *    => Less much data
+ * 4. _qsfp_detect_class_by_extend_comp()
+ *    => Verify 100G CWDM4
+ *    => Verify Obsolete (assigned before 100G CWDM4 MSA required FEC)
+ *    => Verify 100G CLR4
+ *    => Verify 100GE-DWDM2
+ *    => Verify 40G PSM4 Parallel SMF
+ *    => Verify 100G ACC (Active Copper Cable) or 25GAUI C2M ACC.
+ *    => Verify 100G ACC or 25GAUI C2M ACC.
+ *    => Verify 25GBASE-LR
+ *    => Verify 40G Active Cable (XLPPI)
+ */
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h
new file mode 100644
index 000000000000..f17b7fde71b1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h
@@ -0,0 +1,815 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef TRANSCEIVER_H
+#define TRANSCEIVER_H
+
+#include <linux/types.h>
+
+/* advanced features control */
+#define TRANSVR_INFO_DUMP_ENABLE        (1)
+#define TRANSVR_INFO_CACHE_ENABLE       (1)
+#define TRANSVR_UEVENT_ENABLE           (1)
+
+/* Transceiver type define */
+#define TRANSVR_TYPE_UNKNOW_1           (0x00)
+#define TRANSVR_TYPE_UNKNOW_2           (0xff)
+#define TRANSVR_TYPE_SFP                (0x03)  /* Define for SFP, SFP+, SFP28 */
+#define TRANSVR_TYPE_QSFP               (0x0c)
+#define TRANSVR_TYPE_QSFP_PLUS          (0x0d)
+#define TRANSVR_TYPE_QSFP_28            (0x11)
+#define TRANSVR_TYPE_UNPLUGGED          (0xfa)  /* Define for ERROR handle */
+#define TRANSVR_TYPE_FAKE               (0xfc)  /* Define for ERROR handle */
+#define TRANSVR_TYPE_INCONSISTENT       (0xfd)  /* Define for ERROR handle */
+#define TRANSVR_TYPE_ERROR              (0xfe)  /* Define for ERROR handle */
+
+/* Transceiver class for base info */
+#define TRANSVR_CLASS_UNSPECIFIED       (0)
+#define TRANSVR_CLASS_ERROR             (-26001)
+#define TRANSVR_CLASS_1G                (26001)
+#define TRANSVR_CLASS_10G               (26011)
+#define TRANSVR_CLASS_25G               (26021)
+#define TRANSVR_CLASS_40G               (26041)
+#define TRANSVR_CLASS_100G              (26101)
+#define TRANSVR_CLASS_NO_SPERARABLE     (26901)
+#define TRANSVR_CLASS_EXTEND_COMP       (26902)
+/* Transceiver class for Optical 1G */
+#define TRANSVR_CLASS_OPTICAL           (27000)
+#define TRANSVR_CLASS_OPTICAL_100       (27001)
+#define TRANSVR_CLASS_OPTICAL_1G        (27002)
+#define TRANSVR_CLASS_OPTICAL_1G_AOC    (27003)
+#define TRANSVR_CLASS_OPTICAL_1G_SX     (27004)
+#define TRANSVR_CLASS_OPTICAL_1G_LX     (27005)
+#define TRANSVR_CLASS_OPTICAL_1G_EX     (27006)
+/* Transceiver class for Optical 10G */
+#define TRANSVR_CLASS_OPTICAL_10G       (27010)
+#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011)
+#define TRANSVR_CLASS_OPTICAL_10G_S_SR  (27012)
+#define TRANSVR_CLASS_OPTICAL_10G_S_LR  (27013)
+#define TRANSVR_CLASS_OPTICAL_10G_S_ER  (27014)
+#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015)
+#define TRANSVR_CLASS_OPTICAL_10G_Q_SR  (27016)
+#define TRANSVR_CLASS_OPTICAL_10G_Q_LR  (27017)
+#define TRANSVR_CLASS_OPTICAL_10G_Q_ER  (27018)
+/* Transceiver class for Optical 25G */
+#define TRANSVR_CLASS_OPTICAL_25G       (27020)
+#define TRANSVR_CLASS_OPTICAL_25G_AOC   (27021)
+#define TRANSVR_CLASS_OPTICAL_25G_SR    (27022)
+#define TRANSVR_CLASS_OPTICAL_25G_LR    (27023)
+#define TRANSVR_CLASS_OPTICAL_25G_ER    (27024)
+/* Transceiver class for Optical 40G */
+#define TRANSVR_CLASS_OPTICAL_40G       (27040)
+#define TRANSVR_CLASS_OPTICAL_40G_AOC   (27041)
+#define TRANSVR_CLASS_OPTICAL_40G_SR4   (27042)
+#define TRANSVR_CLASS_OPTICAL_40G_LR4   (27043)
+#define TRANSVR_CLASS_OPTICAL_40G_ER4   (27044)
+/* Transceiver class for Optical 100G */
+#define TRANSVR_CLASS_OPTICAL_100G      (27100)
+#define TRANSVR_CLASS_OPTICAL_100G_AOC  (27101)
+#define TRANSVR_CLASS_OPTICAL_100G_SR4  (27102)
+#define TRANSVR_CLASS_OPTICAL_100G_LR4  (27103)
+#define TRANSVR_CLASS_OPTICAL_100G_ER4  (27104)
+#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105)
+/* Transceiver class for Copper */
+#define TRANSVR_CLASS_COPPER            (28000)
+#define TRANSVR_CLASS_COPPER_L1_1G      (28001)
+#define TRANSVR_CLASS_COPPER_L1_10G     (28011)
+#define TRANSVR_CLASS_COPPER_L4_10G     (28012)
+#define TRANSVR_CLASS_COPPER_L1_25G     (28021)
+#define TRANSVR_CLASS_COPPER_L4_40G     (28041)
+#define TRANSVR_CLASS_COPPER_L4_100G    (28101)
+/* Transceiver class for Base-T */
+#define TRANSVR_CLASS_BASE_T_1000       (29001)
+#define TRANSVR_CLASS_BASE_T_1000_up    (29002)
+/* For uevent message */
+#define TRANSVR_UEVENT_KEY_IF           "IF_TYPE"
+#define TRANSVR_UEVENT_KEY_SP           "IF_SPEED"
+#define TRANSVR_UEVENT_KEY_LANE         "IF_LANE"
+#define TRANSVR_UEVENT_UNKNOW           "UNKNOW"
+#define TRANSVR_IF_KR                   "KR"
+#define TRANSVR_IF_KR4                  "KR4"
+#define TRANSVR_IF_SR                   "SR"
+#define TRANSVR_IF_SR4                  "SR4"
+#define TRANSVR_IF_SFI                  "SFI"
+#define TRANSVR_IF_IF_GMII              "GMII"
+#define TRANSVR_IF_IF_XGMII             "XGMII"
+#define TRANSVR_IF_SP_100               "100"
+#define TRANSVR_IF_SP_1G                "1000"
+#define TRANSVR_IF_SP_10G               "10000"
+#define TRANSVR_IF_SP_25G               "25000"
+#define TRANSVR_IF_SP_40G               "40000"
+#define TRANSVR_IF_SP_100G              "100000"
+
+/* Transceiver mode define */
+#define TRANSVR_MODE_DIRECT             (21000)
+#define TRANSVR_MODE_POLLING            (21001)
+
+/* Transceiver state define
+ * [Note]
+ *  1. State is used to represent the state of "Transceiver" and "Object".
+ *  2. State for different target has different means. The description as following:
+ */
+#define STATE_TRANSVR_CONNECTED         (0)    /* [Transvr]:Be plugged in.  [Obj]:Link up,   and work normally.       */
+#define STATE_TRANSVR_NEW               (-100) /* [Transvr]:(Not used)      [Obj]:Create                              */
+#define STATE_TRANSVR_INIT              (-101) /* [Transvr]:Be plugged in.  [Obj]:Link up,   and in initial process.  */
+#define STATE_TRANSVR_ISOLATED          (-102) /* [Transvr]:Be plugged in.  [Obj]:Isolate,   and not provide service. */
+#define STATE_TRANSVR_SWAPPED           (-200) /* [Transvr]:Be plugged in.  [Obj]:(Not used)                          */
+#define STATE_TRANSVR_DISCONNECTED      (-300) /* [Transvr]:Un-plugged.     [Obj]:Link down, and not provide service. */
+#define STATE_TRANSVR_UNEXCEPTED        (-901) /* [Transvr]:Any             [Obj]:Any,       and not in expect case.  */
+
+/* Task state define */
+#define STATE_T_TASK_WAIT               (110)
+#define STATE_T_TASK_DONE               (0)
+#define STATE_T_TASK_INIT               (-110)
+#define STATE_T_TASK_FAIL               (-410)
+
+
+/* Event for task handling */
+#define EVENT_TRANSVR_TASK_WAIT         (2101)
+#define EVENT_TRANSVR_TASK_DONE         (0)
+#define EVENT_TRANSVR_TASK_FAIL         (-2101)
+/* Event for initial handling */
+#define EVENT_TRANSVR_INIT_UP           (2201)
+#define EVENT_TRANSVR_INIT_DOWN         (1)
+#define EVENT_TRANSVR_INIT_REINIT       (-2201)
+#define EVENT_TRANSVR_INIT_FAIL         (-2202)
+/* Event for others */
+#define EVENT_TRANSVR_RELOAD_FAIL       (-2301)
+#define EVENT_TRANSVR_EXCEP_INIT        (-2401)
+#define EVENT_TRANSVR_EXCEP_UP          (-2402)
+#define EVENT_TRANSVR_EXCEP_DOWN        (-2403)
+#define EVENT_TRANSVR_EXCEP_SWAP        (-2404)
+#define EVENT_TRANSVR_EXCEP_EXCEP       (-2405)
+#define EVENT_TRANSVR_EXCEP_ISOLATED    (-2406)
+#define EVENT_TRANSVR_I2C_CRASH         (-2501)
+
+/* Transceiver error code define */
+#define ERR_TRANSVR_UNINIT              (-201)
+#define ERR_TRANSVR_UNPLUGGED           (-202)
+#define ERR_TRANSVR_ABNORMAL            (-203)
+#define ERR_TRANSVR_NOSTATE             (-204)
+#define ERR_TRANSVR_NOTSUPPORT          (-205)
+#define ERR_TRANSVR_BADINPUT            (-206)
+#define ERR_TRANSVR_UPDATE_FAIL         (-207)
+#define ERR_TRANSVR_RELOAD_FAIL         (-208)
+#define ERR_TRANSVR_INIT_FAIL           (-209)
+#define ERR_TRANSVR_UNDEFINED           (-210)
+#define ERR_TRANSVR_TASK_FAIL           (-211)
+#define ERR_TRANSVR_TASK_BUSY           (-212)
+#define ERR_TRANSVR_UEVENT_FAIL         (-213)
+#define ERR_TRANSVR_FUNC_DISABLE        (-214)
+#define ERR_TRANSVR_I2C_CRASH           (-297)
+#define ERR_TRNASVR_BE_ISOLATED         (-298)
+#define ERR_TRANSVR_UNEXCPT             (-299)
+
+/* For debug */
+#define DEBUG_TRANSVR_INT_VAL           (-99)
+#define DEBUG_TRANSVR_HEX_VAL           (0xfe)
+#define DEBUG_TRANSVR_STR_VAL           "ERROR"
+
+/* For system internal */
+#define VAL_TRANSVR_COMID_ARREESS       (0x50)
+#define VAL_TRANSVR_COMID_OFFSET        (0x00)
+#define VAL_TRANSVR_EXTPHY_ADDR_56      (0x56)
+#define VAL_TRANSVR_8472_READY_ADDR     (0x51)
+#define VAL_TRANSVR_8472_READY_PAGE     (-1)
+#define VAL_TRANSVR_8472_READY_OFFSET   (110)
+#define VAL_TRANSVR_8472_READY_BIT      (0)
+#define VAL_TRANSVR_8472_READY_VALUE    (0)
+#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff)
+#define VAL_TRANSVR_8436_READY_ADDR     (0x50)
+#define VAL_TRANSVR_8436_READY_PAGE     (-1)
+#define VAL_TRANSVR_8436_READY_OFFSET   (2)
+#define VAL_TRANSVR_8436_READY_BIT      (0)
+#define VAL_TRANSVR_8436_READY_VALUE    (0)
+#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff)
+#define VAL_TRANSVR_8436_PWD_ADDR       (0x50)
+#define VAL_TRANSVR_8436_PWD_PAGE       (-1)
+#define VAL_TRANSVR_8436_PWD_OFFSET     (123)
+#define VAL_TRANSVR_PAGE_FREE           (-99)
+#define VAL_TRANSVR_PAGE_SELECT_OFFSET  (127)
+#define VAL_TRANSVR_PAGE_SELECT_DELAY   (5)
+#define VAL_TRANSVR_TASK_RETRY_FOREVER  (-999)
+#define VAL_TRANSVR_FUNCTION_DISABLE    (-1)
+#define STR_TRANSVR_SFP                 "SFP"
+#define STR_TRANSVR_QSFP                "QSFP"
+#define STR_TRANSVR_QSFP_PLUS           "QSFP+"
+#define STR_TRANSVR_QSFP28              "QSFP28"
+
+/* For transvr buf len */
+#define LEN_TRANSVR_S_STR               (16)
+#define LEN_TRANSVR_M_STR               (32)
+#define LEN_TRANSVR_L_STR               (64)
+
+/* Optical wavelength */
+#define VAL_OPTICAL_WAVELENGTH_SR       (850)
+#define VAL_OPTICAL_WAVELENGTH_LR       (1310)
+#define VAL_OPTICAL_WAVELENGTH_ER       (1550)
+
+/* BCM chip type define */
+#define BCM_CHIP_TYPE_TRIDENT_2         (31001)  /* Magnolia, Hudson32i, Spruce */
+#define BCM_CHIP_TYPE_TOMAHAWK          (31002)  /* Redwood, Cypress, Sequoia */
+#define BCM_CHIP_TYPE_TRIDENT_3         (31003)  /* Maple */
+
+#define BF_CHIP_TYPE_TOFINO             (31011)  /* Lavender */
+
+/* Info from transceiver EEPROM */
+struct eeprom_map_s {
+    int addr_br;           int page_br;           int offset_br;           int length_br;
+    int addr_cdr;          int page_cdr;          int offset_cdr;          int length_cdr;
+    int addr_comp_rev;     int page_comp_rev;     int offset_comp_rev;     int length_comp_rev;
+    int addr_connector;    int page_connector;    int offset_connector;    int length_connector;
+    int addr_diag_type;    int page_diag_type;    int offset_diag_type;    int length_diag_type;
+    int addr_extbr;        int page_extbr;        int offset_extbr;        int length_extbr;
+    int addr_ext_id;       int page_ext_id;       int offset_ext_id;       int length_ext_id;
+    int addr_id;           int page_id;           int offset_id;           int length_id;
+    int addr_len_sm;       int page_len_sm;       int offset_len_sm;       int length_len_sm;
+    int addr_len_smf;      int page_len_smf;      int offset_len_smf;      int length_len_smf;
+    int addr_len_om1;      int page_len_om1;      int offset_len_om1;      int length_len_om1;
+    int addr_len_om2;      int page_len_om2;      int offset_len_om2;      int length_len_om2;
+    int addr_len_om3;      int page_len_om3;      int offset_len_om3;      int length_len_om3;
+    int addr_len_om4;      int page_len_om4;      int offset_len_om4;      int length_len_om4;
+    int addr_option;       int page_option;       int offset_option;       int length_option;
+    int addr_rate_id;      int page_rate_id;      int offset_rate_id;      int length_rate_id;
+    int addr_rx_am;        int page_rx_am;        int offset_rx_am;        int length_rx_am;
+    int addr_rx_em;        int page_rx_em;        int offset_rx_em;        int length_rx_em;
+    int addr_rx_los;       int page_rx_los;       int offset_rx_los;       int length_rx_los;
+    int addr_rx_power;     int page_rx_power;     int offset_rx_power;     int length_rx_power;
+    int addr_soft_rs0;     int page_soft_rs0;     int offset_soft_rs0;     int length_soft_rs0;
+    int addr_soft_rs1;     int page_soft_rs1;     int offset_soft_rs1;     int length_soft_rs1;
+    int addr_temp;         int page_temp;         int offset_temp;         int length_temp;
+    int addr_trancomp;     int page_trancomp;     int offset_trancomp;     int length_trancomp;
+    int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext;
+    int addr_tx_bias;      int page_tx_bias;      int offset_tx_bias;      int length_tx_bias;
+    int addr_tx_disable;   int page_tx_disable;   int offset_tx_disable;   int length_tx_disable;
+    int addr_tx_eq;        int page_tx_eq;        int offset_tx_eq;        int length_tx_eq;
+    int addr_tx_fault;     int page_tx_fault;     int offset_tx_fault;     int length_tx_fault;
+    int addr_tx_power;     int page_tx_power;     int offset_tx_power;     int length_tx_power;
+    int addr_vendor_name;  int page_vendor_name;  int offset_vendor_name;  int length_vendor_name;
+    int addr_vendor_pn;    int page_vendor_pn;    int offset_vendor_pn;    int length_vendor_pn;
+    int addr_vendor_rev;   int page_vendor_rev;   int offset_vendor_rev;   int length_vendor_rev;
+    int addr_vendor_sn;    int page_vendor_sn;    int offset_vendor_sn;    int length_vendor_sn;
+    int addr_voltage;      int page_voltage;      int offset_voltage;      int length_voltage;
+    int addr_wavelength;   int page_wavelength;   int offset_wavelength;   int length_wavelength;
+};
+
+
+struct transvr_worker_s;
+
+/* Class of transceiver object */
+struct transvr_obj_s {
+
+    /* ========== Object private property ==========
+     * [Prop]: id
+     * [Desc]: Type of serial transceiver.
+     * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h
+     */
+    uint8_t id;
+
+    /* [Prop]: connector
+     * [Desc]: Connector type.
+     * [Note]: SFP : A0h / 2
+     *         QSFP: 00h / 130
+     */
+    uint8_t connector;
+
+    /* [Prop]: transvr_comp
+     * [Desc]: Transceiver compliance code.
+     * [Note]: SFP: SFF-8472
+     *         - Normal  : A0h / offset 3-10
+     *         - Extended: A0h / offset 36
+     *         QSFP: SFF-8436 & SFF-8636
+     *         - Normal  : 00h / offset 131-138
+     *         - Extended: 00h / offset 192
+     */
+    uint8_t transvr_comp[8];
+    uint8_t transvr_comp_ext;
+
+    /* [Prop]: vendor_name
+     * [Desc]: SFP vendor name (ASCII 16 byte char).
+     * [Note]: ex:FINISAR CORP.
+     */
+    char *vendor_name;
+
+    /* [Prop]: vendor_pn
+     * [Desc]: Part number provided by SFP vendor (ASCII 16 byte char).
+     * [Note]:
+     */
+    char *vendor_pn;
+
+    /* [Prop]: vendor_rev
+     * [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char).
+     * [Note]:
+     */
+    char *vendor_rev;
+
+    /* [Prop]: vendor_sn
+     * [Desc]: Serial number provided by vendor (ASCII 16 byte char).
+     * [Note]:
+     */
+    char *vendor_sn;
+
+    /* [Prop]: Extended identifier
+     * [Desc]: SFP:
+     *         => None
+     *
+     *         QSFP:
+     *         => This byte contained two information:
+     *         (1) Power consumption class
+     *         (2) CDR function present
+     * [Note]: Bit description as below:
+     *         [SFP]
+     *           None
+     *
+     *         [QSFP]
+     *         (1) Power consumption class:
+     *             Class 1: 1.5W (Bit6-7 = 00:)
+     *             Class 2: 2.0W (Bit6-7 = 01:)
+     *             Class 3: 2.5W (Bit6-7 = 10:)
+     *             Class 4: 3.5W (Bit6-7 = 11:)
+     *             Class 5: 4.0W (Bit0-1 = 01:)
+     *             Class 6: 4.5W (Bit0-1 = 10:)
+     *             Class 7: 5.0W (Bit0-1 = 11:)
+     *         (2) CDR function present:
+     *             Bit2: 0 = No CDR in RX
+     *                   1 = CDR present in RX
+     *             Bit3: 0 = No CDR in TX
+     *                   1 = CDR present in TX
+     */
+    uint8_t ext_id;
+
+    /* [Prop]: br
+     * [Desc]: Nominal bit rate, units of 100 MBits/sec.
+     * [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh
+     *         has val: 0x67
+     *         no val :
+     */
+    uint8_t br;
+
+    /* [Prop]: extbr
+     * [Desc]: Extended br (00h/222)
+     * [Desc]: Nominal bit rate per channel, units of 250 Mbps.
+     *         Complements. Byte 140. See Table 32A.
+     */
+    uint8_t extbr;
+
+    /* [Prop]: len_sm
+     * [Desc]: Length (single mode)-(100's)m
+     * [Note]: This value specifies the link length that is supported by the transceiver
+     *         while operating in compliance with the applicable standards using single mode
+     *         fiber. The value is in units of 100 meters. A value of 255 means that the
+     *         transceiver supports a link length greater than 25.4 km. A value of zero means
+     *         that the transceiver does not support single mode fiber or that the length
+     *         information must be determined from the transceiver technology.
+     */
+    int len_sm;
+
+    /* [Prop]: len_smf
+     * [Desc]: Length (single mode)-km
+     * [Note]: Addition to EEPROM data from original GBIC definition. This value specifies
+     *         the link length that is supported by the transceiver while operating in
+     *         compliance with the applicable standards using single mode fiber. The value
+     *         is in units of kilometers. A value of 255 means that the transceiver supports
+     *         a link length greater than 254 km. A value of zero means that the transceiver
+     *         does not support single mode fiber or that the length information must be
+     *         determined from the transceiver technology.
+     */
+    int len_smf;
+
+    /* [Prop]: len_om1
+     * [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m
+     * [Note]: The value is in units of 10 meters. A value of 255 means that the
+     *         transceiver supports a link length greater than 2.54 km. A value of
+     *         zero means that the transceiver does not support 50 micron multi-mode
+     *         fiber or that the length information must be determined from the transceiver
+     *         technology.
+     */
+    int len_om1;
+
+    /* [Prop]: len_om2
+     * [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m
+     * [Note]: The value is in units of 10 meters. A value of 255 means that the
+     *         transceiver supports a link length greater than 2.54 km. A value of
+     *         zero means that the transceiver does not support 50 micron multi-mode
+     *         fiber or that the length information must be determined from the transceiver
+     *         technology.
+     */
+    int len_om2;
+
+    /* [Prop]: len_om3
+     * [Desc]: Length (50um, OM3)
+     * [Note]: This value specifies link length that is supported by the transceiver while
+     *         operating in compliance with applicable standards using 50 micron multimode
+     *         OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255
+     *         means that the transceiver supports a link length greater than 2.54 km. A value
+     *         of zero means that the transceiver does not support 50 micron multimode fiber
+     *         or that the length information must be determined from the transceiver technology.
+     */
+    int len_om3;
+
+    /* [Prop]: len_om4
+     * [Desc]: Length (50um, OM4) and Length (Active Cable or Copper)
+     * [Note]: For optical links, this value specifies link length that is supported by the
+     *         transceiver while operating in compliance with applicable standards using 50 micron
+     *         multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of
+     *         255 means that the transceiver supports a link length greater than 2.54 km. A value
+     *         of zero means that the transceiver does not support 50 micron multimode fiber or that
+     *         the length information must be determined from the transceiver codes specified in Table 5-3.
+     *
+     *         For copper links, this value specifies minimum link length supported by the transceiver
+     *         while operating in compliance with applicable standards using copper cable. For active
+     *         cable, this value represents actual length. The value is in units of 1 meter. A value of 255
+     *         means the transceiver supports a link length greater than 254 meters. A value of zero means
+     *         the transceiver does not support copper or active cables or the length information must be
+     *         determined from transceiver technology. Further information about cable design, equalization,
+     *         and connectors is usually required to guarantee meeting a particular length requirement.
+     */
+    int len_om4;
+
+    /* [Prop]: comp_rev
+     * [Desc]: SFF spec revision compliance
+     * [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver
+     *         complies with. (unsigned integer)
+     */
+    uint8_t comp_rev;
+
+    /* [Prop]: CDR
+     * [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal
+     *         retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which
+     *         directs traffic around the internal CDR. (Reference: SFF-8636)
+     * [Note]: value=0xff: ON.
+     *         value=0x00: OFF.
+     */
+    uint8_t cdr;
+
+    /* [Prop]: rate_id
+     * [Desc]: Soft Rate Select 0(RX).
+     * [Note]: 1. Addr: A0h / Offset: 13
+     *         2. Value description:
+     *            00h  Unspecified
+     *            01h  SFF-8079 (4/2/1G Rate_Select & AS0/AS1)
+     *            02h  SFF-8431 (8/4/2G Rx Rate_Select only)
+     *            03h  Unspecified *
+     *            04h  SFF-8431 (8/4/2G Tx Rate_Select only)
+     *            05h  Unspecified *
+     *            06h  SFF-8431 (8/4/2G Independent Rx & Tx Rate_select)
+     *            07h  Unspecified *
+     *            08h  FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G
+     *            09h  Unspecified *
+     *            0Ah  FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only,
+     *                 Low=8G/4G
+     *            0Bh  Unspecified *
+     *            0Ch  FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)
+     *                 High=32G only, Low = 16G/8G
+     *            0Dh  Unspecified *
+     *            0Eh  10/8G Rx and Tx Rate_Select controlling the operation or locking
+     *                 modes of the internal signal conditioner, retimer or CDR, according
+     *                 to the logic table defined in Table 10-2, High Bit Rate
+     *                 (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode,
+     *                 the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11)
+     *                 and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1.
+     *            0Fh  Unspecified *
+     *            10h-FFh Unallocated
+     */
+    int rate_id;
+
+    /* [Prop]: soft_rs0
+     * [Desc]: Soft Rate Select 0(RX).
+     * [Note]: 1. Writing '1' selects full bandwidth operation.
+     *         2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value.
+     *         3. Default at power up is logic zero/low
+     *         4. Addr: A2h / Offset: 110 / Bit: 3
+     */
+    uint8_t soft_rs0;
+
+    /* [Prop]: soft_rs1
+     * [Desc]: Soft Rate Select 1(TX).
+     * [Note]: 1. Writing '1' selects full bandwidth TX operation.
+     *         2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value.
+     *         3. Default at power up is logic zero/low
+     *         4. Addr: A2h / Offset: 118 / Bit: 3
+     */
+    uint8_t soft_rs1;
+
+    /* [Prop]: diag_type
+     * [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92)
+     * [Note]: Description in SFF-8472 as below:
+     *         Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance
+     *               with this document.
+     *         Bit6: Digital diagnostic monitoring implemented (described in this document).
+     *               Must be '1' for compliance with this document.
+     *         Bit5 Internally calibrated
+     *         Bit4 Externally calibrated
+     *         Bit3 Received power measurement type.0 = OMA, 1 = average power
+     *         Bit2 Address change required see section above, "addressing modes"
+     *         Bit1-0 Unallocated
+     */
+    uint8_t diag_type;
+
+    /* [Prop]: curr_temp
+     * [Desc]: Transceiver Current Temperature (A2h/96-97)
+     * [Note]: 1. Dependent on diag_type.
+     *         2. 96: High byte
+     *         3. 97: Low byte
+     *         4. This feature only for SFP
+     */
+    uint8_t curr_temp[2];
+
+    /* [Prop]: curr_vol
+     * [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23)
+     * [Note]: 1. Dependent on diag_type.
+     *         2. 98: High byte
+     *         3. 99: Low byte
+     *         4. This feature only for SFP
+     *         5. Internally measured transceiver supply voltage. Represented
+     *            as a 16 bit unsigned integer with the voltage defined as the
+     *            full 16 bit value (0-65535) with LSB equal to 100 uVolt,
+     *            yielding a total range of 0 to +6.55 Volts
+     */
+    uint8_t curr_voltage[2];
+
+    /* [Prop]: curr_tx_bias
+     * [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27)
+     * [Note]: 1. Dependent on diag_type.
+     *         2. 100: High byte
+     *         3. 101: Low byte
+     *         4. This feature only for SFP
+     *         5. Measured TX bias current in uA. Represented as a 16 bit unsigned
+     *            integer with the current defined as the full 16 bit value (0-65535)
+     *            with LSB equal to 2 uA, yielding a total range of 0 to 131 mA.
+     *            Accuracy is vendor specific but must be better than 10% of the
+     *            manufacturer's nominal value over specified operating temperature
+     *            and voltage.
+     */
+    uint8_t curr_tx_bias[8];
+
+    /* [Prop]: curr_tx_power
+     * [Desc]: Transceiver TX Output Power (A2h/102-103)
+     * [Note]: 1. Dependent on diag_type.
+     *         2. 102: High byte
+     *         3. 103: Low byte
+     *         4. This feature only for SFP
+     *         5. Measured TX output power in mW. Represented as a 16 bit unsigned
+     *         integer with the power defined as the full 16 bit value (0-65535)
+     *         with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW
+     *         (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of
+     *         laser monitor photodiode current. It is factory calibrated to absolute
+     *         units using the most representative fiber output type. Accuracy is
+     *         vendor specific but must be better than 3dB over specified temperature
+     *          and voltage. Data is not valid when the transmitter is disabled.
+     */
+    uint8_t curr_tx_power[8];
+
+    /* [Prop]: curr_tx_power
+     * [Desc]: Transceiver TX Output Power (A2h/102-103)
+     * [Note]: 1. Dependent on diag_type.
+     *         2. 102: High byte
+     *         3. 103: Low byte
+     *         4. This feature only for SFP
+     *         5. Measured RX received optical power in mW. Value can represent either
+     *         average received power or OMA depending upon how bit 3 of byte 92 (A0h)
+     *         is set. Represented as a 16 bit unsigned integer with the power defined
+     *         as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a
+     *         total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is
+     *         dependent upon the exact optical wavelength. For the vendor specified
+     *         wavelength, accuracy shall be better than 3dB over specified temperature
+     *         and voltage.
+     */
+    uint8_t curr_rx_power[8];
+
+    /* [Prop]: wavelength
+     * [Desc]: Wavelength or Copper Cable Attenuation
+     * [Note]: (Following is info from SFF-8636)
+     *         For optical free side devices, this parameter identifies the nominal
+     *         transmitter output wavelength at room temperature. This parameter is a
+     *         16-bit hex value with Byte 186 as high order byte and Byte 187 as low
+     *         order byte. The laser wavelength is equal to the 16-bit integer value
+     *         divided by 20 in nm (units of 0.05 nm). This resolution should be adequate
+     *         to cover all relevant wavelengths yet provide enough resolution for all
+     *         expected DWDM applications. For accurate representation of controlled
+     *         wavelength applications, this value should represent the center of the
+     *         guaranteed wavelength range. If the free side device is identified as
+     *         copper cable these registers will be used to define the cable attenuation.
+     *         An indication of 0 dB attenuation refers to the case where the attenuation
+     *         is not known or is unavailable.
+     *         Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB.
+     *         Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB.
+     */
+    uint8_t wavelength[2];
+
+    /* [Prop]: Amplitude control
+     * [Desc]: Amplitude control
+     * [Note]: QSFP28  => SFF-8636 03H Byte-238/239
+     */
+    uint8_t rx_am[2];
+
+    /* [Prop]: Emphasis control
+     * [Desc]: Emphasis control
+     * [Note]: SFP+/28 => SFF-8472 A2H Byte-115
+     *         QSFP28  => SFF-8636 03H Byte-236/237
+     */
+    uint8_t rx_em[2];
+
+    /* [Prop]: Soft Rx LOS
+     * [Desc]: Soft Rx LOS which provide by transceiver
+     * [Note]: (Following is info from SFF-8636)
+     *         Byte 3:
+     *          - Bit 0: L-Rx1 LOS
+     *          - Bit 1: L-Rx2 LOS
+     *          - Bit 2: L-Rx3 LOS
+     *          - Bit 3: L-Rx4 LOS
+     */
+    uint8_t rx_los;
+
+    /* [Prop]: Soft Tx Disable
+     * [Desc]: Soft Tx Disable which provide by transceiver
+     * [Note]: (Following is info from SFF-8636)
+     *         Byte 86:
+     *          - Bit 0: Tx1 Disable
+     *          - Bit 1: Tx2 Disable
+     *          - Bit 2: Tx3 Disable
+     *          - Bit 3: Tx4 Disable
+     */
+    uint8_t tx_disable;
+
+    /* [Prop]: Soft Tx Fault
+     * [Desc]: Soft Tx Fault which provide by transceiver
+     * [Note]: (Following is info from SFF-8636)
+     *         Byte 86:
+     *          - Bit 0: Tx1 Fault
+     *          - Bit 1: Tx2 Fault
+     *          - Bit 2: Tx3 Fault
+     *          - Bit 3: Tx4 Fault
+     */
+    uint8_t tx_fault;
+
+    /* [Prop]: Transceiver EQUALIZATION
+     * [Desc]: Transceiver EQUALIZATION
+     * [Note]: SFP+/28 => SFF-8472 A2H Byte-114
+     *         QSFP28  => SFF-8636 03H Byte-234/235
+     */
+    uint8_t tx_eq[2];
+
+    /* [Prop]: OPTION VALUES
+     * [Desc]: The bits in the option field shall specify the options implemented in the transceiver.
+     * [Note]: SFP+/28  => SFF-8472 A0H Byte-64/65
+     *         QSFP+/28 => SFF-8636 00H Byte-193/195
+     */
+    uint8_t option[3];
+
+    /* [Prop]: External PHY offset
+     * [Desc]: It needs to be setup first if you want to access transceiver external phy.
+     * [Note]: This feature dependent on transceiver.
+     *         Currently, only 1G-RJ45 transceiver supported it.
+     */
+    uint8_t extphy_offset;
+
+    /* ========== Object private property ==========
+     */
+    struct device       *transvr_dev_p;
+    struct eeprom_map_s *eeprom_map_p;
+    struct i2c_client   *i2c_client_p;
+    struct ioexp_obj_s  *ioexp_obj_p;
+    struct transvr_worker_s *worker_p;
+    struct mutex lock;
+    char swp_name[32];
+    int auto_config;
+    int auto_tx_disable;
+    int chan_id;
+    int chipset_type;
+    int curr_page;
+    int info;
+    int ioexp_virt_offset;
+    int lane_id[8];
+    int layout;
+    int mode;
+    int retry;
+    int state;
+    int temp;
+    int type;
+
+    /* ========== Object public functions ==========
+     */
+    int  (*get_id)(struct transvr_obj_s *self);
+    int  (*get_ext_id)(struct transvr_obj_s *self);
+    int  (*get_connector)(struct transvr_obj_s *self);
+    int  (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_power_cls)(struct transvr_obj_s *self);
+    int  (*get_br)(struct transvr_obj_s *self);
+    int  (*get_len_sm)(struct transvr_obj_s *self);
+    int  (*get_len_smf)(struct transvr_obj_s *self);
+    int  (*get_len_om1)(struct transvr_obj_s *self);
+    int  (*get_len_om2)(struct transvr_obj_s *self);
+    int  (*get_len_om3)(struct transvr_obj_s *self);
+    int  (*get_len_om4)(struct transvr_obj_s *self);
+    int  (*get_comp_rev)(struct transvr_obj_s *self);
+    int  (*get_comp_eth_1)(struct transvr_obj_s *self);
+    int  (*get_comp_eth_10)(struct transvr_obj_s *self);
+    int  (*get_comp_eth_10_40)(struct transvr_obj_s *self);
+    int  (*get_comp_extend)(struct transvr_obj_s *self);
+    int  (*get_cdr)(struct transvr_obj_s *self);
+    int  (*get_rate_id)(struct transvr_obj_s *self);
+    int  (*get_soft_rs0)(struct transvr_obj_s *self);
+    int  (*get_soft_rs1)(struct transvr_obj_s *self);
+    int  (*get_info)(struct transvr_obj_s *self);
+    int  (*get_if_type)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_if_speed)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_if_lane)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_tx_power)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_rx_power)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_rx_am)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_rx_em)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_wavelength)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p);
+    int  (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p);
+    int  (*set_cdr)(struct transvr_obj_s *self, int input_val);
+    int  (*set_soft_rs0)(struct transvr_obj_s *self, int input_val);
+    int  (*set_soft_rs1)(struct transvr_obj_s *self, int input_val);
+    int  (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val);
+    int  (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val);
+    int  (*set_tx_eq)(struct transvr_obj_s *self, int input_val);
+    int  (*set_rx_am)(struct transvr_obj_s *self, int input_val);
+    int  (*set_rx_em)(struct transvr_obj_s *self, int input_val);
+    int  (*set_extphy_offset)(struct transvr_obj_s *self, int input_val);
+    int  (*set_extphy_reg)(struct transvr_obj_s *self, int input_val);
+
+    /* ========== Object private functions ==========
+     */
+    int (*init)(struct transvr_obj_s *self);
+    int (*clean)(struct transvr_obj_s *self);
+    int (*check)(struct transvr_obj_s *self);
+    int (*update_all)(struct transvr_obj_s *self, int show_err);
+    int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name);
+    int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name);
+    int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action);
+    int (*dump_all)(struct transvr_obj_s* self);
+};
+
+
+/* For AVL Mapping */
+struct transvr_avl_s {
+    char vendor_name[32];
+    char vendor_pn[32];
+    int (*init)(struct transvr_obj_s *self);
+};
+
+
+/* Worker for long term task of transceiver */
+struct transvr_worker_s {
+    /* Task Parameter */
+    struct transvr_obj_s *transvr_p;
+    struct transvr_worker_s *next_p;
+    struct transvr_worker_s *pre_p;
+    unsigned long trigger_time;
+    char func_name[64];
+    int retry;
+    int state;
+
+    /* Task private data */
+    void *p_data;
+
+    /* Call back function */
+    int (*main_task)(struct transvr_worker_s *task);
+    int (*post_task)(struct transvr_worker_s *task);
+};
+
+
+struct transvr_obj_s *
+create_transvr_obj(char *swp_name,
+                   int chan_id,
+                   struct ioexp_obj_s *ioexp_obj_p,
+                   int ioexp_virt_offset,
+                   int transvr_type,
+                   int chipset_type,
+                   int run_mode);
+
+void lock_transvr_obj(struct transvr_obj_s *self);
+void unlock_transvr_obj(struct transvr_obj_s *self);
+int isolate_transvr_obj(struct transvr_obj_s *self);
+
+int resync_channel_tier_2(struct transvr_obj_s *self);
+
+void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg);
+
+#endif /* TRANSCEIVER_H */
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py
new file mode 100755
index 000000000000..e3e696c088cd
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 Inventec, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Usage: %(scriptName)s [options] command object
+
+options:
+    -h | --help     : this help message
+    -d | --debug    : run with debug mode
+    -f | --force    : ignore error during installation or clean 
+command:
+    install         : install drivers and generate related sysfs nodes
+    clean           : uninstall drivers and remove related sysfs nodes
+"""
+
+import os
+import commands
+import sys, getopt
+import logging
+import re
+import time
+from collections import namedtuple
+
+DEBUG = False
+args = []
+FORCE = 0
+i2c_prefix = '/sys/bus/i2c/devices/'
+
+
+if DEBUG == True:
+    print sys.argv[0]
+    print 'ARGV: ', sys.argv[1:]
+
+
+def main():
+    global DEBUG
+    global args
+    global FORCE
+
+
+    if len(sys.argv)<2:
+        show_help()
+
+    options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
+                                                       'debug',
+                                                       'force',
+                                                          ])
+    if DEBUG == True:
+        print options
+        print args
+        print len(sys.argv)
+
+    for opt, arg in options:
+        if opt in ('-h', '--help'):
+            show_help()
+        elif opt in ('-d', '--debug'):
+            DEBUG = True
+            logging.basicConfig(level=logging.INFO)
+        elif opt in ('-f', '--force'):
+            FORCE = 1
+        else:
+            logging.info('no option')
+    for arg in args:
+        if arg == 'install':
+            install()
+        elif arg == 'clean':
+            uninstall()
+        else:
+            show_help()
+
+
+    return 0
+
+def show_help():
+    print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
+    sys.exit(0)
+
+def show_log(txt):
+    if DEBUG == True:
+        print "[D6356]"+txt
+    return
+
+def exec_cmd(cmd, show):
+    logging.info('Run :'+cmd)
+    status, output = commands.getstatusoutput(cmd)
+    show_log (cmd +" with result:" + str(status))
+    show_log ("      output:"+output)
+    if status:
+        logging.info('Failed :'+cmd)
+        if show:
+            print('Failed :'+cmd)
+    return  status, output
+
+
+instantiate = [
+'echo inv_eeprom 0x55 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device'
+#'echo inv_cpld 0x33 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device',
+#'echo inv_cpld 0x77 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device'
+]
+
+
+drivers =[
+#kernel-dirvers
+'lpc_ich',
+'i2c-i801',
+'i2c-mux',
+'i2c-mux-pca954x',
+'i2c-mux-pca9541',
+'i2c-dev',
+'ucd9000',
+#inv-modules
+'inv_eeprom',
+'inv_cpld',
+'inv_platform',
+'monitor',
+'swps']
+
+
+
+def system_install():
+    global FORCE
+
+    #remove default drivers to avoid modprobe order conflicts
+    status, output = exec_cmd("rmmod i2c_ismt ", 1)
+    status, output = exec_cmd("rmmod i2c-i801 ", 1)
+    status, output = exec_cmd("rmmod gpio_ich ", 1)
+    status, output = exec_cmd("rmmod lpc_ich ", 1)
+
+    #insert extra module
+    status, output = exec_cmd("insmod /lib/modules/3.16.0-5-amd64/extra/gpio-ich.ko gpiobase=0",1)
+
+    #install drivers
+    for i in range(0,len(drivers)):
+       status, output = exec_cmd("modprobe "+drivers[i], 1)
+    if status:
+	   print output
+	   if FORCE == 0:
+	      return status
+
+    #instantiate devices
+    for i in range(0,len(instantiate)):
+       #time.sleep(1)
+       status, output = exec_cmd(instantiate[i], 1)
+    if status:
+	   print output
+	   if FORCE == 0:                
+	      return status
+
+    #swps map to i2c-bus
+    for i in range(14,22):
+        status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-6/i2c-"+str(i)+"/new_device", 1)
+        if status:
+            print output
+            if FORCE == 0:
+                return status
+    for i in range(22,30):
+        status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-7/i2c-"+str(i)+"/new_device", 1)
+        status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-7/i2c-"+str(i)+"/new_device", 1)
+        if status:
+            print output
+            if FORCE == 0:
+                return status
+    for i in range(30,38):
+        status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-8/i2c-"+str(i)+"/new_device", 1)
+        status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-8/i2c-"+str(i)+"/new_device", 1)
+        if status:
+            print output
+            if FORCE == 0:
+                return status
+    for i in range(38,46):
+        status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-9/i2c-"+str(i)+"/new_device", 1)
+        status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-9/i2c-"+str(i)+"/new_device", 1)
+        if status:
+            print output
+            if FORCE == 0:
+                return status
+    for i in range(46,54):
+        status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-10/i2c-"+str(i)+"/new_device", 1)
+        status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-10/i2c-"+str(i)+"/new_device", 1)
+        if status:
+            print output
+            if FORCE == 0:
+                return status
+    for i in range(54,62):
+        status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-11/i2c-"+str(i)+"/new_device", 1)
+        status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-11/i2c-"+str(i)+"/new_device", 1)
+        if status:
+            print output
+            if FORCE == 0:
+                return status
+    for i in range(62,70):
+        status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-12/i2c-"+str(i)+"/new_device", 1)
+        status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-12/i2c-"+str(i)+"/new_device", 1)
+        if status:
+            print output
+            if FORCE == 0:
+                return status
+    return
+
+
+def system_ready():
+    if not device_found():
+        return False
+    return True
+
+def install():
+    if not device_found():
+        print "No device, installing...."
+        status = system_install()
+        if status:
+            if FORCE == 0:
+                return status
+    else:
+        print "D6356 devices detected...."
+    return
+
+def uninstall():
+    global FORCE
+    #uninstall drivers
+    exec_cmd("rmmod gpio_ich",1)
+    for i in range(len(drivers)-1,-1,-1):
+       status, output = exec_cmd("rmmod "+drivers[i], 1)
+    if status:
+	   print output
+	   if FORCE == 0:
+	      return status
+    return
+
+def device_found():
+    ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0)
+    ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-5", 0)
+    return not(ret1 or ret2)				
+
+if __name__ == "__main__":
+    main()
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/control b/platform/broadcom/sonic-platform-modules-inventec/debian/control
index 0c9b5822b060..742df27be46d 100644
--- a/platform/broadcom/sonic-platform-modules-inventec/debian/control
+++ b/platform/broadcom/sonic-platform-modules-inventec/debian/control
@@ -25,6 +25,11 @@ Architecture: amd64
 Depends: linux-image-4.9.0-8-2-amd64
 Description: kernel modules for platform devices such as fan, led
 
+Package: platform-modules-d6356
+Architecture: amd64
+Depends: linux-image-4.9.0-8-2-amd64
+Description: kernel modules for platform devices such as fan, led
+
 Package: platform-modules-d7264q28b
 Architecture: amd64
 Depends: linux-image-4.9.0-8-2-amd64
diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.init b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.init
new file mode 100644
index 000000000000..eaeb97406a1c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.init
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides:          setup-board
+# Required-Start:
+# Required-Stop:
+# Should-Start:
+# Should-Stop:
+# Default-Start:     S
+# Default-Stop:      0 6
+# Short-Description: Setup Inventec d6356 board.
+### END INIT INFO
+
+PLATFORM_DIR=/usr/share/sonic/device/x86_64-inventec_d6356-r0/plugins
+
+PLATFORM_DAEMON=$PLATFORM_DIR/platfmgr.py
+PLATFORM_DAEMON_NAME=platfmgr
+
+# The process ID of the script when it runs is stored here:
+PLATFORM_PIDFILE=/var/run/$PLATFORM_DAEMON_NAME.pid
+
+do_monitor_start() {
+    /sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_PIDFILE --make-pidfile --startas $PLATFORM_DAEMON --start --background -- $DAEMON_OPTS
+}
+
+do_monitor_stop() {
+    /sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_PIDFILE --retry 10
+}
+
+case "$1" in
+start)
+	echo -n "Setting up board... "
+	
+#	depmod -a
+	/usr/local/bin/inventec_d6356_util.py -f install
+        do_monitor_${1}
+	echo "done."
+	;;
+
+stop)
+    
+        /usr/local/bin/inventec_d6356_util.py -f clean
+        do_monitor_${1}
+	echo "done."
+
+	;;
+
+force-reload|restart)
+	echo "Not supported"
+	;;
+
+*)
+	echo "Usage: /etc/init.d/platform-modules-d6356.init {start|stop}"
+	exit 1
+	;;
+esac
+
+exit 0
diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install
new file mode 100644
index 000000000000..4c668b9816c4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install
@@ -0,0 +1 @@
+d6356/utils/inventec_d6356_util.py              /usr/local/bin
diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/rules b/platform/broadcom/sonic-platform-modules-inventec/debian/rules
index 2e396e167822..8bfe6e6582d9 100755
--- a/platform/broadcom/sonic-platform-modules-inventec/debian/rules
+++ b/platform/broadcom/sonic-platform-modules-inventec/debian/rules
@@ -14,7 +14,7 @@ export INSTALL_MOD_DIR:=extra
 KVERSION   ?= $(shell uname -r)
 KERNEL_SRC :=  /lib/modules/$(KVERSION)
 MOD_SRC_DIR:= $(shell pwd)
-MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d7264q28b
+MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d6356 d7264q28b
 
 %:
 	dh $@ --with=systemd