diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini
new file mode 100644
index 000000000000..24823135f4ca
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/port_config.ini
@@ -0,0 +1,74 @@
+# name lanes alias
+Ethernet0 16 Ethernet0
+Ethernet4 15 Ethernet4
+Ethernet8 14 Ethernet8
+Ethernet12 13 Ethernet12
+Ethernet16 24 Ethernet16
+Ethernet20 23 Ethernet20
+Ethernet24 22 Ethernet24
+Ethernet28 21 Ethernet28
+Ethernet32 28 Ethernet32
+Ethernet36 27 Ethernet36
+Ethernet40 26 Ethernet40
+Ethernet44 25 Ethernet44
+Ethernet48 32 Ethernet48
+Ethernet52 31 Ethernet52
+Ethernet56 30 Ethernet56
+Ethernet60 29 Ethernet60
+Ethernet64 48 Ethernet64
+Ethernet68 47 Ethernet68
+Ethernet72 46 Ethernet72
+Ethernet76 45 Ethernet76
+Ethernet80 52 Ethernet80
+Ethernet84 51 Ethernet84
+Ethernet88 50 Ethernet88
+Ethernet92 49 Ethernet92
+Ethernet96 56 Ethernet96
+Ethernet100 55 Ethernet100
+Ethernet104 54 Ethernet104
+Ethernet108 53 Ethernet108
+Ethernet112 60 Ethernet112
+Ethernet116 59 Ethernet116
+Ethernet120 58 Ethernet120
+Ethernet124 57 Ethernet124
+Ethernet128 64 Ethernet128
+Ethernet132 63 Ethernet132
+Ethernet136 62 Ethernet136
+Ethernet140 61 Ethernet140
+Ethernet144 68 Ethernet144
+Ethernet148 67 Ethernet148
+Ethernet152 66 Ethernet152
+Ethernet156 65 Ethernet156
+Ethernet160 72 Ethernet160
+Ethernet164 71 Ethernet164
+Ethernet168 70 Ethernet168
+Ethernet172 69 Ethernet172
+Ethernet176 76 Ethernet176
+Ethernet180 75 Ethernet180
+Ethernet184 74 Ethernet184
+Ethernet188 73 Ethernet188
+Ethernet192 82 Ethernet192
+Ethernet196 84 Ethernet196
+Ethernet200 81 Ethernet200
+Ethernet204 83 Ethernet204
+Ethernet208 78 Ethernet208
+Ethernet212 80 Ethernet212
+Ethernet216 77 Ethernet216
+Ethernet220 79 Ethernet220
+Ethernet224 98 Ethernet224
+Ethernet228 100 Ethernet228
+Ethernet232 97 Ethernet232
+Ethernet236 99 Ethernet236
+Ethernet240 104 Ethernet240
+Ethernet244 102 Ethernet244
+Ethernet248 103 Ethernet248
+Ethernet252 101 Ethernet252
+Ethernet256 108 Ethernet256
+Ethernet260 106 Ethernet260
+Ethernet264 107 Ethernet264
+Ethernet268 105 Ethernet268
+Ethernet272 112 Ethernet272
+Ethernet276 110 Ethernet276
+Ethernet280 111 Ethernet280
+Ethernet284 109 Ethernet284
+
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile
new file mode 100644
index 000000000000..3f549dd63b40
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/sai.profile
@@ -0,0 +1,2 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-d6254qs-72x10G.config
+SAI_NUM_ECMP_MEMBERS=32
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm
new file mode 100644
index 000000000000..66b7172bce7c
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/INVENTEC-D6254QS/td2-d6254qs-72x10G.config.bcm
@@ -0,0 +1,160 @@
+os=unix
+parity_enable=0
+pbmp_xport_xe.0=0x1fffffffffffffffffffffffffffffffe
+miim_intr_enable=0
+schan_intr_enable=0
+bcm_stat_interval=2000000
+serdes_firmware_mode_xe=0x2
+
+portmap_1=16:10
+portmap_2=15:10
+portmap_3=14:10
+portmap_4=13:10
+portmap_5=24:10
+portmap_6=23:10
+portmap_7=22:10
+portmap_8=21:10
+portmap_9=28:10
+portmap_10=27:10
+portmap_11=26:10
+portmap_12=25:10
+portmap_13=32:10
+portmap_14=31:10
+portmap_15=30:10
+portmap_16=29:10
+portmap_17=48:10
+portmap_18=47:10
+portmap_19=46:10
+portmap_20=45:10
+portmap_21=52:10
+portmap_22=51:10
+portmap_23=50:10
+portmap_24=49:10
+portmap_25=56:10
+portmap_26=55:10
+portmap_27=54:10
+portmap_28=53:10
+portmap_29=60:10
+portmap_30=59:10
+portmap_31=58:10
+portmap_32=57:10
+portmap_33=64:10
+portmap_34=63:10
+portmap_35=62:10
+portmap_36=61:10
+portmap_37=68:10
+portmap_38=67:10
+portmap_39=66:10
+portmap_40=65:10
+portmap_41=72:10
+portmap_42=71:10
+portmap_43=70:10
+portmap_44=69:10
+portmap_45=76:10
+portmap_46=75:10
+portmap_47=74:10
+portmap_48=73:10
+
+portmap_49=82:10
+portmap_50=84:10
+portmap_51=81:10
+portmap_52=83:10
+
+portmap_53=78:10
+portmap_54=80:10
+portmap_55=77:10
+portmap_56=79:10
+
+portmap_57=98:10
+portmap_58=100:10
+portmap_59=97:10
+portmap_60=99:10
+
+portmap_61=104:10
+portmap_62=102:10
+portmap_63=103:10
+portmap_64=101:10
+
+portmap_65=108:10
+portmap_66=106:10
+portmap_67=107:10
+portmap_68=105:10
+
+portmap_69=112:10
+portmap_70=110:10
+portmap_71=111:10
+portmap_72=109:10
+
+xgxs_rx_lane_map_xe0=0x0123
+xgxs_rx_lane_map_xe1=0x0123
+xgxs_rx_lane_map_xe2=0x0123
+xgxs_rx_lane_map_xe3=0x0123
+xgxs_rx_lane_map_xe4=0x0123
+xgxs_rx_lane_map_xe5=0x0123
+xgxs_rx_lane_map_xe6=0x0123
+xgxs_rx_lane_map_xe7=0x0123
+xgxs_rx_lane_map_xe8=0x0123
+xgxs_rx_lane_map_xe9=0x0123
+xgxs_rx_lane_map_xe10=0x0123
+xgxs_rx_lane_map_xe11=0x0123
+xgxs_rx_lane_map_xe12=0x0123
+xgxs_rx_lane_map_xe13=0x0123
+xgxs_rx_lane_map_xe14=0x0123
+xgxs_rx_lane_map_xe15=0x0123
+xgxs_rx_lane_map_xe16=0x0123
+xgxs_rx_lane_map_xe17=0x0123
+xgxs_rx_lane_map_xe18=0x0123
+xgxs_rx_lane_map_xe19=0x0123
+xgxs_rx_lane_map_xe20=0x0123
+xgxs_rx_lane_map_xe21=0x0123
+xgxs_rx_lane_map_xe22=0x0123
+xgxs_rx_lane_map_xe23=0x0123
+xgxs_rx_lane_map_xe24=0x0123
+xgxs_rx_lane_map_xe25=0x0123
+xgxs_rx_lane_map_xe26=0x0123
+xgxs_rx_lane_map_xe27=0x0123
+xgxs_rx_lane_map_xe28=0x0123
+xgxs_rx_lane_map_xe29=0x0123
+xgxs_rx_lane_map_xe30=0x0123
+xgxs_rx_lane_map_xe31=0x0123
+xgxs_rx_lane_map_xe32=0x0123
+xgxs_rx_lane_map_xe33=0x0123
+xgxs_rx_lane_map_xe34=0x0123
+xgxs_rx_lane_map_xe35=0x0123
+xgxs_rx_lane_map_xe36=0x0123
+xgxs_rx_lane_map_xe37=0x0123
+xgxs_rx_lane_map_xe38=0x0123
+xgxs_rx_lane_map_xe39=0x0123
+xgxs_rx_lane_map_xe40=0x0123
+xgxs_rx_lane_map_xe41=0x0123
+xgxs_rx_lane_map_xe42=0x0123
+xgxs_rx_lane_map_xe43=0x0123
+xgxs_rx_lane_map_xe44=0x0123
+xgxs_rx_lane_map_xe45=0x0123
+xgxs_rx_lane_map_xe46=0x0123
+xgxs_rx_lane_map_xe47=0x0123
+xgxs_rx_lane_map_xe48=0x0123
+xgxs_rx_lane_map_xe49=0x0123
+xgxs_rx_lane_map_xe50=0x0123
+xgxs_rx_lane_map_xe51=0x0123
+xgxs_rx_lane_map_xe52=0x0123
+xgxs_rx_lane_map_xe53=0x0123
+xgxs_rx_lane_map_xe54=0x0123
+xgxs_rx_lane_map_xe55=0x0123
+xgxs_rx_lane_map_xe56=0x0123
+xgxs_rx_lane_map_xe57=0x0123
+xgxs_rx_lane_map_xe58=0x0123
+xgxs_rx_lane_map_xe59=0x0123
+xgxs_rx_lane_map_xe60=0x0123
+xgxs_rx_lane_map_xe61=0x0123
+xgxs_rx_lane_map_xe62=0x0123
+xgxs_rx_lane_map_xe63=0x0123
+xgxs_rx_lane_map_xe64=0x0123
+xgxs_rx_lane_map_xe65=0x0123
+xgxs_rx_lane_map_xe66=0x0123
+xgxs_rx_lane_map_xe67=0x0123
+xgxs_rx_lane_map_xe68=0x0123
+xgxs_rx_lane_map_xe69=0x0123
+xgxs_rx_lane_map_xe70=0x0123
+xgxs_rx_lane_map_xe71=0x0123
+
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf b/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf
new file mode 100644
index 000000000000..6b489db6e16f
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/installer.conf
@@ -0,0 +1,4 @@
+CONSOLE_PORT=0x2f8
+CONSOLE_DEV=1
+CONSOLE_SPEED=115200
+VAR_LOG_SIZE=1024
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc
new file mode 100644
index 000000000000..92423b234498
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/led_proc_init.soc
@@ -0,0 +1,136 @@
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=31
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=30
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=29
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=28
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=27
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=26
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=25
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=24
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=23
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=22
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=21
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=20
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=19
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=18
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=17
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=16
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=15
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=14
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=13
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=12
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=11
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=10
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=9
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=8
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=7
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=6
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=5
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=4
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=3
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=2
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=1
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=0
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=63
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=62
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=61
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=60
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=59
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=58
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=57
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=56
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=55
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=54
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=53
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=52
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=51
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=50
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=49
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=48
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=47
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=46
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=45
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=44
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=43
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=42
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=41
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=40
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=39
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=38
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=37
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=36
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=35
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=34
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=33
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=32
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=2
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=1
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=0
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=6
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=5
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=4
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=10
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=9
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=8
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=14
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=13
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=12
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=18
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=17
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=16
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=22
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=21
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=20
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=26
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=25
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=24
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=30
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=29
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=28
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=34
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=33
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=32
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=38
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=37
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=36
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=42
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=41
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=40
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=46
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=45
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=44
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=50
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=49
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=48
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=54
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=53
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=52
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=58
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=57
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=56
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=62
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=61
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60
+
+led 0 stop
+led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57
+led 0 start
+
+led 1 stop
+led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57
+led 1 start
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml b/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml
new file mode 100644
index 000000000000..e2368e171b58
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/minigraph.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+ OCPSCH0104001MS
+ 10.10.1.26
+ SONiC-Inventec-d6254qs
+ 10.10.1.25
+ 1
+ 10
+ 3
+
+
+ OCPSCH0104002MS
+ 10.10.2.26
+ SONiC-Inventec-d6254qs
+ 10.10.2.25
+ 1
+ 10
+ 3
+
+
+
+
+ 64536
+ SONiC-Inventec-d6254qs
+
+
+ 10.10.1.26
+
+
+
+
+ 10.10.2.26
+
+
+
+
+
+
+
+ 64542
+ OCPSCH0104001MS
+
+
+
+ 64543
+ OCPSCH0104002MS
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 100.0.0.9/32
+
+ 100.0.0.9/32
+
+
+
+
+
+
+
+ SONiC-Inventec-d6254qs
+
+
+
+
+
+ Ethernet0
+ 10.10.1.25/30
+
+
+
+ Ethernet4
+ 10.10.2.25/30
+
+
+
+
+
+
+
+
+
+
+
+ DeviceInterfaceLink
+ OCPSCH0104001MS
+ Ethernet24
+ SONiC-Inventec-d6254qs
+ Ethernet0
+
+
+ DeviceInterfaceLink
+ OCPSCH0104002MS
+ Ethernet24
+ SONiC-Inventec-d6254qs
+ Ethernet4
+
+
+
+
+ SONiC-Inventec-d6254qs
+ INVENTEC-D6254QS
+
+
+
+
+
+
+ SONiC-Inventec-d6254qs
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+
+
+
+
+ SONiC-Inventec-d6254qs
+ INVENTEC-D6254QS
+
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..de5c24ba0e6d
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/eeprom.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Inventec d7032q28b
+#
+# 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/class/i2c-adapter/i2c-0/0-0053/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/psuutil.py
new file mode 100644
index 000000000000..4bd3f7a27052
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-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/bus/i2c/devices/0-0066"
+
+ 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
+ :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
+ :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-1
+ 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_d6254qs-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/sfputil.py
new file mode 100644
index 000000000000..6cd470795fb6
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/plugins/sfputil.py
@@ -0,0 +1,209 @@
+# 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 = 53
+ PORTS_IN_BLOCK = 54
+ QSFP_PORT_START = 48
+ QSFP_PORT_END = 53
+
+ _port_to_eeprom_mapping = {}
+ port_to_i2c_mapping = {
+ 0: 10,
+ 1: 11,
+ 2: 12,
+ 3: 13,
+ 4: 14,
+ 5: 15,
+ 6: 16,
+ 7: 17,
+ 8: 18,
+ 9: 19,
+ 10: 20,
+ 11: 21,
+ 12: 22,
+ 13: 23,
+ 14: 24,
+ 15: 25,
+ 16: 26,
+ 17: 27,
+ 18: 28,
+ 19: 29,
+ 20: 30,
+ 21: 31,
+ 22: 32,
+ 23: 33,
+ 24: 34,
+ 25: 35,
+ 26: 36,
+ 27: 37,
+ 28: 38,
+ 29: 39,
+ 30: 40,
+ 31: 41,
+ 32: 42,
+ 33: 43,
+ 34: 44,
+ 35: 45,
+ 36: 46,
+ 37: 47,
+ 38: 48,
+ 39: 49,
+ 40: 50,
+ 41: 51,
+ 42: 52,
+ 43: 53,
+ 44: 54,
+ 45: 55,
+ 46: 56,
+ 47: 57,
+ 48: 58,
+ 49: 59,
+ 50: 60,
+ 51: 61,
+ 52: 62,
+ 53: 63
+ }
+
+ @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
diff --git a/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf b/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf
new file mode 100644
index 000000000000..653900cad36f
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6254qs-r0/sensors.conf
@@ -0,0 +1,15 @@
+# libsensors configuration file
+chip "inv_psoc-*"
+ ignore temp3
+ ignore temp4
+ label temp1 "CPU Board Temperature"
+ label temp2 "SW Board I Temperature"
+ label temp5 "SW Board II Temperature"
+ label temp6 "ASIC Temperature"
+ label in1 "PSU1 Voltage"
+ label in2 "PSU2 Voltage"
+ label curr1 "PSU1 Current"
+ label curr2 "PSU2 Current"
+ label power1 "PSU1 Power"
+ label power2 "PSU2 Power"
+
diff --git a/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini
new file mode 100644
index 000000000000..4af8faabf676
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/port_config.ini
@@ -0,0 +1,57 @@
+# name lanes alias
+Ethernet0 1 Ethernet0
+Ethernet4 2 Ethernet4
+Ethernet8 3 Ethernet8
+Ethernet12 4 Ethernet12
+Ethernet16 5 Ethernet16
+Ethernet20 6 Ethernet20
+Ethernet24 7 Ethernet24
+Ethernet28 8 Ethernet28
+Ethernet32 13 Ethernet32
+Ethernet36 14 Ethernet36
+Ethernet40 15 Ethernet40
+Ethernet44 16 Ethernet44
+Ethernet48 21 Ethernet48
+Ethernet52 22 Ethernet52
+Ethernet56 23 Ethernet56
+Ethernet60 24 Ethernet60
+Ethernet64 29 Ethernet64
+Ethernet68 30 Ethernet68
+Ethernet72 31 Ethernet72
+Ethernet76 32 Ethernet76
+Ethernet80 33 Ethernet80
+Ethernet84 34 Ethernet84
+Ethernet88 35 Ethernet88
+Ethernet92 36 Ethernet92
+Ethernet96 41 Ethernet96
+Ethernet100 42 Ethernet100
+Ethernet104 43 Ethernet104
+Ethernet108 44 Ethernet108
+Ethernet112 49 Ethernet112
+Ethernet116 50 Ethernet116
+Ethernet120 51 Ethernet120
+Ethernet124 52 Ethernet124
+Ethernet128 57 Ethernet128
+Ethernet132 58 Ethernet132
+Ethernet136 59 Ethernet136
+Ethernet140 60 Ethernet140
+Ethernet144 61 Ethernet144
+Ethernet148 62 Ethernet148
+Ethernet152 63 Ethernet152
+Ethernet156 64 Ethernet156
+Ethernet160 65 Ethernet160
+Ethernet164 66 Ethernet164
+Ethernet168 67 Ethernet168
+Ethernet172 68 Ethernet172
+Ethernet176 69 Ethernet176
+Ethernet180 70 Ethernet180
+Ethernet184 71 Ethernet184
+Ethernet188 72 Ethernet188
+Ethernet192 77,78,79,80 Ethernet192
+Ethernet196 85,86,87,88 Ethernet196
+Ethernet200 93,94,95,96 Ethernet200
+Ethernet204 97,98,99,100 Ethernet204
+Ethernet208 105,106,107,108 Ethernet208
+Ethernet212 113,114,115,116 Ethernet212
+Ethernet216 121,122,123,124 Ethernet216
+Ethernet220 125,126,127,128 Ethernet220
diff --git a/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile
new file mode 100644
index 000000000000..6f0bf54024a7
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-r0/INVENTEC-D6556/sai.profile
@@ -0,0 +1,2 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6556-48x25G-8x100G.config.bcm.inventec
+SAI_NUM_ECMP_MEMBERS=32
diff --git a/device/inventec/x86_64-inventec_d6556-r0/installer.conf b/device/inventec/x86_64-inventec_d6556-r0/installer.conf
new file mode 100644
index 000000000000..1db64ba02c38
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-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_d6556-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6556-r0/led_proc_init.soc
new file mode 100644
index 000000000000..d4c2fde64f9c
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-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_d6556-r0/minigraph.xml b/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml
new file mode 100644
index 000000000000..50b3a05cfcce
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-r0/minigraph.xml
@@ -0,0 +1,144 @@
+
+
+
+
+
+ OCPSCH0104001MS
+ 10.10.1.26
+ SONiC-Inventec-d6556
+ 10.10.1.25
+ 1
+ 10
+ 3
+
+
+ OCPSCH0104002MS
+ 10.10.2.26
+ SONiC-Inventec-d6556
+ 10.10.2.25
+ 1
+ 10
+ 3
+
+
+
+
+ 64536
+ SONiC-Inventec-d6556
+
+
+ 10.10.1.26
+
+
+
+
+ 10.10.2.26
+
+
+
+
+
+
+
+ 64542
+ OCPSCH0104001MS
+
+
+
+ 64543
+ OCPSCH0104002MS
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 100.0.0.9/32
+
+ 100.0.0.9/32
+
+
+
+
+
+
+
+ SONiC-Inventec-d6556
+
+
+
+
+
+ Ethernet0
+ 10.10.1.25/30
+
+
+
+ Ethernet4
+ 10.10.2.25/30
+
+
+
+
+
+
+
+
+
+
+
+ DeviceInterfaceLink
+ OCPSCH0104001MS
+ Ethernet24
+ SONiC-Inventec-d6556
+ Ethernet0
+
+
+ DeviceInterfaceLink
+ OCPSCH0104002MS
+ Ethernet24
+ SONiC-Inventec-d6556
+ Ethernet4
+
+
+
+
+ SONiC-Inventec-d6556
+ INVENTEC-D6556
+
+
+
+
+
+
+ SONiC-Inventec-d6556
+
+
+ DhcpResources
+
+
+
+
+ NtpResources
+
+ 0.debian.pool.ntp.org;1.debian.pool.ntp.org;2.debian.pool.ntp.org;3.debian.pool.ntp.org
+
+
+ SyslogResources
+
+
+
+
+
+
+
+
+ SONiC-Inventec-d6556
+ INVENTEC-D6556
+
diff --git a/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py
new file mode 100644
index 000000000000..de5c24ba0e6d
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-r0/plugins/eeprom.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Inventec d7032q28b
+#
+# 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/class/i2c-adapter/i2c-0/0-0053/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/inventec/x86_64-inventec_d6556-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/psuutil.py
new file mode 100644
index 000000000000..855162f63b98
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-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
+ :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
+ :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-1
+ 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_d6556-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py
new file mode 100644
index 000000000000..155b956827f1
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-r0/plugins/sfputil.py
@@ -0,0 +1,211 @@
+# 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: 18,
+ 1: 19,
+ 2: 20,
+ 3: 21,
+ 4: 22,
+ 5: 23,
+ 6: 24,
+ 7: 25,
+ 8: 26,
+ 9: 27,
+ 10: 28,
+ 11: 29,
+ 12: 30,
+ 13: 31,
+ 14: 32,
+ 15: 33,
+ 16: 34,
+ 17: 35,
+ 18: 36,
+ 19: 37,
+ 20: 38,
+ 21: 39,
+ 22: 40,
+ 23: 41,
+ 24: 42,
+ 25: 43,
+ 26: 44,
+ 27: 45,
+ 28: 46,
+ 29: 47,
+ 30: 48,
+ 31: 49,
+ 32: 50,
+ 33: 51,
+ 34: 52,
+ 35: 53,
+ 36: 54,
+ 37: 55,
+ 38: 56,
+ 39: 57,
+ 40: 58,
+ 41: 59,
+ 42: 60,
+ 43: 61,
+ 44: 62,
+ 45: 63,
+ 46: 64,
+ 47: 65,
+ 48: 10,
+ 49: 11,
+ 50: 12,
+ 51: 13,
+ 52: 14,
+ 53: 15,
+ 54: 16,
+ 55: 17
+ }
+
+ @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
diff --git a/device/inventec/x86_64-inventec_d6556-r0/sensors.conf b/device/inventec/x86_64-inventec_d6556-r0/sensors.conf
new file mode 100644
index 000000000000..98a8e59b9158
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d6556-r0/sensors.conf
@@ -0,0 +1,44 @@
+# libsensors configuration file
+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/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2 b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2
new file mode 100644
index 000000000000..864e3bd9870d
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/buffers.json.j2
@@ -0,0 +1,128 @@
+{# Default values which will be used if no actual configura available #}
+{% set default_cable = '300m' %}
+{% set default_speed = '100G' %}
+{% set default_ports_num = 32 -%}
+
+{# Port configuration to cable length look-up table #}
+{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
+{# Roles described in the minigraph #}
+{% set ports2cable = {
+ 'torrouter_server' : '5m',
+ 'leafrouter_torrouter' : '40m',
+ 'spinerouter_leafrouter' : '300m'
+ }
+%}
+
+{%- macro cable_length(port_name) -%}
+ {%- set cable_len = [] -%}
+ {%- for local_port in DEVICE_NEIGHBOR -%}
+ {%- if local_port == port_name -%}
+ {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor_role = neighbor.type -%}
+ {%- set roles1 = switch_role + '_' + neighbor_role %}
+ {%- set roles2 = neighbor_role + '_' + switch_role -%}
+ {%- set roles1 = roles1 | lower -%}
+ {%- set roles2 = roles2 | lower -%}
+ {%- if roles1 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
+ {%- elif roles2 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if cable_len -%}
+ {{ cable_len.0 }}
+ {%- else -%}
+ {{ default_cable }}
+ {%- endif -%}
+{% endmacro %}
+
+{%- if DEVICE_METADATA is defined %}
+{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
+{%- endif -%}
+
+{# Generate list of ports if not defined #}
+{% if PORT is not defined %}
+ {% set PORT = [] %}
+ {% for port_idx in range(0,default_ports_num) %}
+ {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %}
+ {% endfor %}
+{% endif -%}
+
+{% set port_names_list = [] %}
+{% for port in PORT %}
+ {%- if port_names_list.append(port) %}{% endif %}
+{% endfor %}
+{% set port_names = port_names_list | join(',') -%}
+
+{
+ "CABLE_LENGTH": {
+ "AZURE": {
+ {% for port in PORT %}
+ {% set cable = cable_length(port) -%}
+ "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
+
+ {% endfor %}
+ }
+ },
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "6000000",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "8072396",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "xon":"18432",
+ "xoff":"40560",
+ "size":"41808",
+ "dynamic_th":"-4",
+ "xon_offset":"2496"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"6000000"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+ "BUFFER_PG": {
+ "{{ port_names }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]"
+ },
+ "{{ port_names }}|0-1": {
+ "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]"
+ }
+ },
+ "BUFFER_QUEUE": {
+ "{{ port_names }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|egress_lossless_profile]"
+ },
+ "{{ port_names }}|0-1": {
+ "profile" : "[BUFFER_PROFILE|egress_lossy_profile]"
+ }
+ }
+}
diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json
new file mode 100644
index 000000000000..926911ab59d0
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7032q28b-r0/INVENTEC-D7032Q28B-C32/qos.json
@@ -0,0 +1,143 @@
+{
+ "TC_TO_PRIORITY_GROUP_MAP": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "3": "3",
+ "4": "4"
+ }
+ },
+ "MAP_PFC_PRIORITY_TO_QUEUE": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "3": "3",
+ "4": "4"
+ }
+ },
+ "TC_TO_QUEUE_MAP": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "3": "3",
+ "4": "4"
+ }
+ },
+ "DSCP_TO_TC_MAP": {
+ "AZURE": {
+ "0":"0",
+ "1":"0",
+ "2":"0",
+ "3":"3",
+ "4":"4",
+ "5":"0",
+ "6":"0",
+ "7":"0",
+ "8":"1",
+ "9":"0",
+ "10":"0",
+ "11":"0",
+ "12":"0",
+ "13":"0",
+ "14":"0",
+ "15":"0",
+ "16":"0",
+ "17":"0",
+ "18":"0",
+ "19":"0",
+ "20":"0",
+ "21":"0",
+ "22":"0",
+ "23":"0",
+ "24":"0",
+ "25":"0",
+ "26":"0",
+ "27":"0",
+ "28":"0",
+ "29":"0",
+ "30":"0",
+ "31":"0",
+ "32":"0",
+ "33":"0",
+ "34":"0",
+ "35":"0",
+ "36":"0",
+ "37":"0",
+ "38":"0",
+ "39":"0",
+ "40":"0",
+ "41":"0",
+ "42":"0",
+ "43":"0",
+ "44":"0",
+ "45":"0",
+ "46":"0",
+ "47":"0",
+ "48":"0",
+ "49":"0",
+ "50":"0",
+ "51":"0",
+ "52":"0",
+ "53":"0",
+ "54":"0",
+ "55":"0",
+ "56":"0",
+ "57":"0",
+ "58":"0",
+ "59":"0",
+ "60":"0",
+ "61":"0",
+ "62":"0",
+ "63":"0"
+ }
+ },
+ "SCHEDULER": {
+ "scheduler.0" : {
+ "type":"DWRR",
+ "weight": "25"
+ },
+ "scheduler.1" : {
+ "type":"DWRR",
+ "weight": "30"
+ },
+ "scheduler.2" : {
+ "type":"DWRR",
+ "weight": "20"
+ }
+ },
+ "PORT_QOS_MAP": {
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124": {
+ "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]",
+ "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]",
+ "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]",
+ "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]",
+ "pfc_enable": "3,4"
+ }
+ },
+ "WRED_PROFILE": {
+ "AZURE_LOSSLESS" : {
+ "wred_green_enable":"true",
+ "wred_yellow_enable":"true",
+ "wred_red_enable":"true",
+ "ecn":"ecn_all",
+ "red_max_threshold":"312000",
+ "red_min_threshold":"104000",
+ "yellow_max_threshold":"312000",
+ "yellow_min_threshold":"104000",
+ "green_max_threshold":"312000",
+ "green_min_threshold":"104000"
+ }
+ },
+ "QUEUE": {
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|3-4" : {
+ "scheduler" : "[SCHEDULER|scheduler.0]",
+ "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]"
+ },
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|0" : {
+ "scheduler" : "[SCHEDULER|scheduler.1]"
+ },
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124|1" : {
+ "scheduler" : "[SCHEDULER|scheduler.2]"
+ }
+ }
+}
diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc
index 39ae1f247929..92423b234498 100644
--- a/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc
+++ b/device/inventec/x86_64-inventec_d7032q28b-r0/led_proc_init.soc
@@ -128,9 +128,9 @@ m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=61
m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=60
led 0 stop
-led 0 prog 02 00 60 F1 12 00 DE F6 70 10 67 47 67 42 77 06 06 F2 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DE F4 70 34 86 F0 77 16 12 00 DE F8 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 00 00 00
+led 0 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57
led 0 start
led 1 stop
-led 1 prog 02 00 60 F1 12 00 DE F6 70 10 67 47 67 42 77 06 06 F2 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DE F4 70 34 86 F0 77 16 12 00 DE F8 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57 00 00 00
+led 1 prog 02 00 60 F1 12 00 DA 0F 70 10 67 47 67 42 77 06 02 A0 60 F0 12 00 06 F0 4A 04 27 67 42 4A 03 27 67 42 4A 07 27 67 42 4A 00 27 67 42 DA 80 70 34 86 F0 77 16 12 00 DA 03 70 40 67 4A 67 42 77 36 3E F1 87 86 F1 81 57 17 27 57 07 27 57
led 1 start
diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/minigraph.xml b/device/inventec/x86_64-inventec_d7032q28b-r0/minigraph.xml
index a582bfa49a21..1f1dd3dfe35a 100644
--- a/device/inventec/x86_64-inventec_d7032q28b-r0/minigraph.xml
+++ b/device/inventec/x86_64-inventec_d7032q28b-r0/minigraph.xml
@@ -93,7 +93,6 @@
- 40000
DeviceInterfaceLink
OCPSCH0104001MS
Ethernet24
@@ -101,7 +100,6 @@
Ethernet0
- 40000
DeviceInterfaceLink
OCPSCH0104002MS
Ethernet24
diff --git a/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf
new file mode 100644
index 000000000000..653900cad36f
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7032q28b-r0/sensors.conf
@@ -0,0 +1,15 @@
+# libsensors configuration file
+chip "inv_psoc-*"
+ ignore temp3
+ ignore temp4
+ label temp1 "CPU Board Temperature"
+ label temp2 "SW Board I Temperature"
+ label temp5 "SW Board II Temperature"
+ label temp6 "ASIC Temperature"
+ label in1 "PSU1 Voltage"
+ label in2 "PSU2 Voltage"
+ label curr1 "PSU1 Current"
+ label curr2 "PSU2 Current"
+ label power1 "PSU1 Power"
+ label power2 "PSU2 Power"
+
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2 b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2
new file mode 100644
index 000000000000..ccf463c40526
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/buffers.json.j2
@@ -0,0 +1,128 @@
+{# Default values which will be used if no actual configura available #}
+{% set default_cable = '300m' %}
+{% set default_speed = '100G' %}
+{% set default_ports_num = 54 -%}
+
+{# Port configuration to cable length look-up table #}
+{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
+{# Roles described in the minigraph #}
+{% set ports2cable = {
+ 'torrouter_server' : '5m',
+ 'leafrouter_torrouter' : '40m',
+ 'spinerouter_leafrouter' : '300m'
+ }
+%}
+
+{%- macro cable_length(port_name) -%}
+ {%- set cable_len = [] -%}
+ {%- for local_port in DEVICE_NEIGHBOR -%}
+ {%- if local_port == port_name -%}
+ {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
+ {%- set neighbor_role = neighbor.type -%}
+ {%- set roles1 = switch_role + '_' + neighbor_role %}
+ {%- set roles2 = neighbor_role + '_' + switch_role -%}
+ {%- set roles1 = roles1 | lower -%}
+ {%- set roles2 = roles2 | lower -%}
+ {%- if roles1 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
+ {%- elif roles2 in ports2cable -%}
+ {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endif -%}
+ {%- endfor -%}
+ {%- if cable_len -%}
+ {{ cable_len.0 }}
+ {%- else -%}
+ {{ default_cable }}
+ {%- endif -%}
+{% endmacro %}
+
+{%- if DEVICE_METADATA is defined %}
+{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
+{%- endif -%}
+
+{# Generate list of ports if not defined #}
+{% if PORT is not defined %}
+ {% set PORT = [] %}
+ {% for port_idx in range(0,default_ports_num) %}
+ {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %}
+ {% endfor %}
+{% endif -%}
+
+{% set port_names_list = [] %}
+{% for port in PORT %}
+ {%- if port_names_list.append(port) %}{% endif %}
+{% endfor %}
+{% set port_names = port_names_list | join(',') -%}
+
+{
+ "CABLE_LENGTH": {
+ "AZURE": {
+ {% for port in PORT %}
+ {% set cable = cable_length(port) -%}
+ "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
+
+ {% endfor %}
+ }
+ },
+ "BUFFER_POOL": {
+ "ingress_lossless_pool": {
+ "size": "12766208",
+ "type": "ingress",
+ "mode": "dynamic"
+ },
+ "egress_lossless_pool": {
+ "size": "6000000",
+ "type": "egress",
+ "mode": "static"
+ },
+ "egress_lossy_pool": {
+ "size": "8072396",
+ "type": "egress",
+ "mode": "dynamic"
+ }
+ },
+ "BUFFER_PROFILE": {
+ "ingress_lossless_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "xon":"18432",
+ "xoff":"40560",
+ "size":"41808",
+ "dynamic_th":"-4",
+ "xon_offset":"2496"
+ },
+ "ingress_lossy_profile": {
+ "pool":"[BUFFER_POOL|ingress_lossless_pool]",
+ "size":"0",
+ "dynamic_th":"3"
+ },
+ "egress_lossless_profile": {
+ "pool":"[BUFFER_POOL|egress_lossless_pool]",
+ "size":"0",
+ "static_th":"6000000"
+ },
+ "egress_lossy_profile": {
+ "pool":"[BUFFER_POOL|egress_lossy_pool]",
+ "size":"1518",
+ "dynamic_th":"3"
+ }
+ },
+ "BUFFER_PG": {
+ "{{ port_names }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|ingress_lossless_profile]"
+ },
+ "{{ port_names }}|0-1": {
+ "profile" : "[BUFFER_PROFILE|ingress_lossy_profile]"
+ }
+ },
+ "BUFFER_QUEUE": {
+ "{{ port_names }}|3-4": {
+ "profile" : "[BUFFER_PROFILE|egress_lossless_profile]"
+ },
+ "{{ port_names }}|0-1": {
+ "profile" : "[BUFFER_PROFILE|egress_lossy_profile]"
+ }
+ }
+}
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json
new file mode 100644
index 000000000000..9949a5903d8b
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/INVENTEC-D7054Q28B-S48-Q6/qos.json
@@ -0,0 +1,143 @@
+{
+ "TC_TO_PRIORITY_GROUP_MAP": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "3": "3",
+ "4": "4"
+ }
+ },
+ "MAP_PFC_PRIORITY_TO_QUEUE": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "3": "3",
+ "4": "4"
+ }
+ },
+ "TC_TO_QUEUE_MAP": {
+ "AZURE": {
+ "0": "0",
+ "1": "1",
+ "3": "3",
+ "4": "4"
+ }
+ },
+ "DSCP_TO_TC_MAP": {
+ "AZURE": {
+ "0":"0",
+ "1":"0",
+ "2":"0",
+ "3":"3",
+ "4":"4",
+ "5":"0",
+ "6":"0",
+ "7":"0",
+ "8":"1",
+ "9":"0",
+ "10":"0",
+ "11":"0",
+ "12":"0",
+ "13":"0",
+ "14":"0",
+ "15":"0",
+ "16":"0",
+ "17":"0",
+ "18":"0",
+ "19":"0",
+ "20":"0",
+ "21":"0",
+ "22":"0",
+ "23":"0",
+ "24":"0",
+ "25":"0",
+ "26":"0",
+ "27":"0",
+ "28":"0",
+ "29":"0",
+ "30":"0",
+ "31":"0",
+ "32":"0",
+ "33":"0",
+ "34":"0",
+ "35":"0",
+ "36":"0",
+ "37":"0",
+ "38":"0",
+ "39":"0",
+ "40":"0",
+ "41":"0",
+ "42":"0",
+ "43":"0",
+ "44":"0",
+ "45":"0",
+ "46":"0",
+ "47":"0",
+ "48":"0",
+ "49":"0",
+ "50":"0",
+ "51":"0",
+ "52":"0",
+ "53":"0",
+ "54":"0",
+ "55":"0",
+ "56":"0",
+ "57":"0",
+ "58":"0",
+ "59":"0",
+ "60":"0",
+ "61":"0",
+ "62":"0",
+ "63":"0"
+ }
+ },
+ "SCHEDULER": {
+ "scheduler.0" : {
+ "type":"DWRR",
+ "weight": "25"
+ },
+ "scheduler.1" : {
+ "type":"DWRR",
+ "weight": "30"
+ },
+ "scheduler.2" : {
+ "type":"DWRR",
+ "weight": "20"
+ }
+ },
+ "PORT_QOS_MAP": {
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212": {
+ "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]",
+ "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]",
+ "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]",
+ "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]",
+ "pfc_enable": "3,4"
+ }
+ },
+ "WRED_PROFILE": {
+ "AZURE_LOSSLESS" : {
+ "wred_green_enable":"true",
+ "wred_yellow_enable":"true",
+ "wred_red_enable":"true",
+ "ecn":"ecn_all",
+ "red_max_threshold":"312000",
+ "red_min_threshold":"104000",
+ "yellow_max_threshold":"312000",
+ "yellow_min_threshold":"104000",
+ "green_max_threshold":"312000",
+ "green_min_threshold":"104000"
+ }
+ },
+ "QUEUE": {
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|3-4" : {
+ "scheduler" : "[SCHEDULER|scheduler.0]",
+ "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]"
+ },
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|0" : {
+ "scheduler" : "[SCHEDULER|scheduler.1]"
+ },
+ "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28,Ethernet32,Ethernet36,Ethernet40,Ethernet44,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76,Ethernet80,Ethernet84,Ethernet88,Ethernet92,Ethernet96,Ethernet100,Ethernet104,Ethernet108,Ethernet112,Ethernet116,Ethernet120,Ethernet124,Ethernet128,Ethernet132,Ethernet136,Ethernet140,Ethernet144,Ethernet148,Ethernet152,Ethernet156,Ethernet160,Ethernet164,Ethernet168,Ethernet172,Ethernet176,Ethernet180,Ethernet184,Ethernet188,Ethernet192,Ethernet196,Ethernet200,Ethernet204,Ethernet208,Ethernet212|1" : {
+ "scheduler" : "[SCHEDULER|scheduler.2]"
+ }
+ }
+}
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/minigraph.xml b/device/inventec/x86_64-inventec_d7054q28b-r0/minigraph.xml
index 0e579ccbde14..7cd7dd75e608 100644
--- a/device/inventec/x86_64-inventec_d7054q28b-r0/minigraph.xml
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/minigraph.xml
@@ -93,7 +93,6 @@
- 40000
DeviceInterfaceLink
OCPSCH0104001MS
Ethernet24
@@ -101,7 +100,6 @@
Ethernet0
- 40000
DeviceInterfaceLink
OCPSCH0104002MS
Ethernet24
diff --git a/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf
new file mode 100644
index 000000000000..b3fd61236c9e
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7054q28b-r0/sensors.conf
@@ -0,0 +1,44 @@
+# libsensors configuration file
+chip "inv_psoc-*"
+ label temp1 "FrontSide Temperature"
+ label temp2 "FanBoard Temperature"
+ label temp3 "NearASIC Temperature"
+ label temp4 "NearPSU 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/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm
index 8ca378382c93..a7eaa1d6ac59 100644
--- a/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/INVENTEC-D7264Q28B/th2-d7264q28b-64x100g.config.bcm
@@ -15,12 +15,12 @@ portmap_135=263:10
# 64 ports config for 100G
# For Tomahawk FalconCore:
-# Physical ports in FalconCore[0 - 15] must map to logical port[1 - 32] at any order
-# Physical ports in FalconCore[16 - 31] must map to logical port[34 - 65] at any order
-# Physical ports in FalconCore[32 - 47] must map to logical port[68 - 99] at any order
-# Physical ports in FalconCore[48 - 63] must map to logical port[102 - 133] at any order
+#Physical ports in FalconCore[0-15] must map to logical port[1-32] at any order
+#Physical ports in FalconCore[16-31] must map to logical port[34-65] at any order
+#Physical ports in FalconCore[32-47] must map to logical port[68-99] at any order
+#Physical ports in FalconCore[48-63] must map to logical port[102-133] at any order
-## FalconCore[0 - 15]
+## FalconCore[0-15]
portmap_1=9:100
portmap_2=1:100
portmap_3=13:100
@@ -38,7 +38,7 @@ portmap_14=49:100
portmap_15=61:100
portmap_16=53:100
-## FalconCore[16 - 31]
+## FalconCore[16-31]
portmap_34=73:100
portmap_35=65:100
portmap_36=77:100
@@ -839,3 +839,72 @@ dport_map_port_112=114
dport_map_port_113=115
dport_map_port_114=48
dport_map_port_115=49
+
+## ce
+## POST: 24(18) MAIN: 62(3E) PRE: 8(08)
+serdes_preemphasis_1=0x183E08
+serdes_preemphasis_2=0x193E08
+serdes_preemphasis_5=0x173E08
+serdes_preemphasis_6=0x173E08
+serdes_preemphasis_9=0x163E07
+serdes_preemphasis_10=0x173E08
+serdes_preemphasis_13=0x154007
+serdes_preemphasis_14=0x154007
+serdes_preemphasis_34=0x134007
+serdes_preemphasis_35=0x144007
+serdes_preemphasis_38=0x133F07
+serdes_preemphasis_39=0x133F07
+serdes_preemphasis_42=0x133F07
+serdes_preemphasis_43=0x133F06
+serdes_preemphasis_46=0x113E06
+serdes_preemphasis_47=0x113E05
+serdes_preemphasis_68=0x103F06
+serdes_preemphasis_69=0x103F06
+serdes_preemphasis_72=0x113F06
+serdes_preemphasis_73=0x103F06
+serdes_preemphasis_76=0x124006
+serdes_preemphasis_77=0x124006
+serdes_preemphasis_80=0x144007
+serdes_preemphasis_81=0x144007
+serdes_preemphasis_102=0x144007
+serdes_preemphasis_103=0x144007
+serdes_preemphasis_106=0x153F08
+serdes_preemphasis_107=0x153F08
+serdes_preemphasis_110=0x164008
+serdes_preemphasis_111=0x164008
+serdes_preemphasis_114=0x184008
+serdes_preemphasis_115=0x184008
+serdes_preemphasis_3=0x184108
+serdes_preemphasis_4=0x184108
+serdes_preemphasis_7=0x173F08
+serdes_preemphasis_8=0x174108
+serdes_preemphasis_11=0x154007
+serdes_preemphasis_12=0x154007
+serdes_preemphasis_15=0x144007
+serdes_preemphasis_16=0x144007
+serdes_preemphasis_36=0x133F07
+serdes_preemphasis_37=0x133F07
+serdes_preemphasis_40=0x133F07
+serdes_preemphasis_41=0x123F07
+serdes_preemphasis_44=0x113F07
+serdes_preemphasis_45=0x113F07
+serdes_preemphasis_48=0x113F06
+serdes_preemphasis_49=0x103F06
+serdes_preemphasis_70=0x113F06
+serdes_preemphasis_71=0x103F06
+serdes_preemphasis_74=0x113F06
+serdes_preemphasis_75=0x113F06
+serdes_preemphasis_78=0x123F07
+serdes_preemphasis_79=0x134007
+serdes_preemphasis_82=0x144007
+serdes_preemphasis_83=0x144007
+serdes_preemphasis_104=0x164007
+serdes_preemphasis_105=0x154107
+serdes_preemphasis_108=0x174107
+serdes_preemphasis_109=0x163F07
+serdes_preemphasis_112=0x194107
+serdes_preemphasis_113=0x174107
+serdes_preemphasis_116=0x1B4108
+serdes_preemphasis_117=0x194108
+
+
diff --git a/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf b/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf
new file mode 100644
index 000000000000..38072557730e
--- /dev/null
+++ b/device/inventec/x86_64-inventec_d7264q28b-r0/sensors.conf
@@ -0,0 +1,44 @@
+# libsensors configuration file
+chip "inv_psoc-*"
+ label temp1 "FrontSide Temperature"
+ label temp2 "FanBoard Temperature"
+ label temp3 "NearASIC Temperature"
+ label temp4 "Center(U10) 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/platform-modules-inventec.mk b/platform/broadcom/platform-modules-inventec.mk
index 2a6f32f923c4..ead32e75a815 100644
--- a/platform/broadcom/platform-modules-inventec.mk
+++ b/platform/broadcom/platform-modules-inventec.mk
@@ -1,11 +1,15 @@
-# Inventec d7032q28b , d7054q28b and d7264q28b Platform modules
+# Inventec platform modules
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_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_D7264Q28B_PLATFORM_MODULE_VERSION
INVENTEC_D7032Q28B_PLATFORM_MODULE = platform-modules-d7032q28b_$(INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
@@ -18,6 +22,14 @@ INVENTEC_D7054Q28B_PLATFORM_MODULE = platform-modules-d7054q28b_$(INVENTEC_D7054
$(INVENTEC_D7054Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7054q28b-r0
$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7054Q28B_PLATFORM_MODULE)))
+INVENTEC_D6254QS_PLATFORM_MODULE = platform-modules-d6254qs_$(INVENTEC_D6254QS_PLATFORM_MODULE_VERSION)_amd64.deb
+$(INVENTEC_D6254QS_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6254qs-r0
+$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6254QS_PLATFORM_MODULE)))
+
+INVENTEC_D6556_PLATFORM_MODULE = platform-modules-d6556_$(INVENTEC_D6556_PLATFORM_MODULE_VERSION)_amd64.deb
+$(INVENTEC_D6556_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6556-r0
+$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6556_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)))
diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py
new file mode 100755
index 000000000000..bcb05b9cb845
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/asic_monitor.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 Inventec, Inc.
+#
+# Editor: James Huang ( Huang.James@inventec.com )
+#
+"""
+Usage: %(scriptName)s [options] command object
+
+Auto detecting the Chipset temperature and update
+
+options:
+ -h | --help : this help message
+ -d | --debug : run with debug mode
+
+"""
+
+try:
+ import os
+ import commands
+ import sys, getopt
+ import logging
+ import re
+ import time
+ import syslog
+ from sonic_sfp.bcmshell import bcmshell
+
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+args = []
+INV_REDWOOD_PLATFORM = "SONiC-Inventec-d7032-100"
+INV_CYPRESS_PLATFORM = "SONiC-Inventec-d7054"
+INV_SEQUOIA_PLATFORM = "SONiC-Inventec-d7264"
+INV_MAPLE_PLATFORM = "SONiC-Inventec-d6556"
+INV_MAGNOLIA_PLATFORM = "SONiC-Inventec-d6254qs"
+
+PSOC_NAME = "name"
+HWMON_PATH = "/sys/class/hwmon/"
+SWITCH_TEMP_FILE_NAME = "switch_tmp"
+
+def log_message( level, string ):
+ syslog.openlog("asic_monitor", syslog.LOG_PID, facility=syslog.LOG_DAEMON)
+ syslog.syslog( level, string )
+
+def initialLoop():
+
+ global bcm_obj
+ initialNotOK = True
+
+ while initialNotOK :
+ try:
+ bcm_obj = BCMUtil()
+ bcm_obj.execute_command("echo")
+ initialNotOK = False
+ print bcm_obj
+ log_message( syslog.LOG_INFO, "BCMUtil Object initialed successfully" )
+ except Exception, e:
+ print "Exception. The warning is {0}".format(str(e))
+ time.sleep(10)
+
+class BCMUtil(bcmshell):
+
+ asic_temperature = 0
+ platform = None
+
+ def get_platform(self):
+ if self.platform is None:
+ self.platform = os.popen("uname -n").read().strip()
+ return self.platform
+
+ def get_asic_temperature( self ):
+ return self.asic_temperature
+
+ def set_asic_temperature( self, temp ):
+ self.asic_temperature = temp
+
+ def parsing_asic_temp(self):
+ content = self.run("show temp")
+ for line in content.split("\n"):
+ TempObject = re.search(r"(average current temperature is)\s+(?P\d+)\.(?P\d+)",line)
+ if TempObject is not None:
+ self.set_asic_temperature( int( TempObject.group("temperature_high") ) )
+
+ def execute_command(self, cmd):
+ return self.run(cmd)
+
+
+def main():
+
+ global bcm_obj
+ initialLoop()
+ log_message( syslog.LOG_INFO, "Object initialed successfully" )
+
+ while 1 :
+ try:
+ bcm_obj.parsing_asic_temp()
+ for index in os.listdir(HWMON_PATH):
+ file_list = os.listdir("{0}/{1}/device/".format(HWMON_PATH,index))
+ if PSOC_NAME in file_list :
+ with open( "{0}/{1}/device/{2}".format(HWMON_PATH, index, PSOC_NAME), 'rb') as readPtr:
+ content = readPtr.read().strip()
+ if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM :
+ if content == "inv_bmc" and SWITCH_TEMP_FILE_NAME in file_list :
+ os.system("echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME ))
+ break
+ else :
+ if content == "inv_psoc" and SWITCH_TEMP_FILE_NAME in file_list :
+ print "echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME )
+ os.system("echo {0} > {1}/{2}/device/{3}".format( ( bcm_obj.get_asic_temperature() * 1000 ), HWMON_PATH, index, SWITCH_TEMP_FILE_NAME ))
+ break
+ except Exception, e:
+ log_message( syslog.LOG_WARNING, "Exception. The warning is {0}".format(str(e)) )
+ initialLoop()
+ time.sleep(5)
+
+ syslog.closelog()
+ del bcm_obj
+
+if __name__ == "__main__":
+ main()
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py
index 57c5dfc6035f..bab0e2dafe76 100755
--- a/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py
+++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/led_proc.py
@@ -1,5 +1,19 @@
#!/usr/bin/env python
#
+# Copyright (C) 2018 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 .
import os
import time
@@ -7,20 +21,28 @@
import re
from sonic_sfp.bcmshell import bcmshell
+
# =====================================================================
# global variable init
# =====================================================================
-
+# port object
+PORT_LIST = []
+# object is to execute bcm shell command
+BCM_SHELL = None
+SHELL_READY = False
+# port status that is auto update by chip in data ram
+STATUS_RX = 1<<0
+STATUS_TX = 1<<1
# define data ram address
PORT_DATA_OFFSET_ADDR = 0xA0
-PORT_DATA_START_ADDR = 0xF2
-TOTAL_SCAN_BITS_ADDR = 0xF4
-SYNC_START_LEN_ADDR = 0xF6
-SYNC_STOP_LEN_ADDR = 0xF8
-# bit streaming rule for CPLD decode
-TOTAL_SCAN_BITS = None
-SYNC_S = None
-SYNC_P = None
+# define board type
+INV_MAGNOLIA = "SONiC-Inventec-d6254qs"
+INV_REDWOOD = "SONiC-Inventec-d7032-100"
+INV_CYPRESS = "SONiC-Inventec-d7054"
+INV_MAPLE = "SONiC-Inventec-d6556"
+INV_SEQUOIA = ""
+BOARD_TPYE = ""
+EAGLE_CORE = []
# define port data for bit streaming
BIT_LINK = None
BIT_FAULT = None
@@ -33,86 +55,41 @@
SPEED_40G = 40
SPEED_25G = 25
SPEED_10G = 10
-# the amount of LED processor
-AMOUNT_LED_UP = None
-# define board type
-INV_REDWOOD = "SONiC-Inventec-d7032-100"
-INV_CYPRESS = "SONiC-Inventec-d7054"
-INV_SEQUOIA = ""
-BOARD_TPYE = ""
-EAGLE_CORE = []
-
-PORT_LIST = []
-
-# port status that is auto update by chip in data ram
-# there are two byte to indicate each port status
-'''
-RX equ 0x0 ; received packet
-TX equ 0x1 ; transmitted packet
-COLL equ 0x2 ; collision indicator
-SPEED_C equ 0x3 ; 100 Mbps
-SPEED_M equ 0x4 ; 1000 Mbps
-DUPLEX equ 0x5 ; half/full duplex
-FLOW equ 0x6 ; flow control capable
-LINKUP equ 0x7 ; link down/up status
-LINKEN equ 0x8 ; link disabled/enabled status
-ZERO equ 0xE ; always 0
-ONE equ 0xF ; always 1
-'''
-STATUS_ENABLE = 1<<0
-STATUS_RX = 1<<0
-STATUS_TX = 1<<1
-
-# object is to execute bcm shell command
-BCM_SHELL = None
-
# =====================================================================
# class object
# =====================================================================
-class Led():
-
- up = None
- pfw = None
-
- def __init__(self, led_number, program_fw):
- self.up = led_number
- self.pfw = program_fw
-
- def led_start(self):
- BCM_SHELL.cmd("led {0} start".format(self.up))
- syslog.syslog(syslog.LOG_INFO, "Start Led({0})".format(self.up))
-
- def led_stop(self):
- BCM_SHELL.cmd("led {0} stop".format(self.up))
- syslog.syslog(syslog.LOG_INFO, "Stop Led({0})".format(self.up))
-
- def load_prog(self):
- BCM_SHELL.cmd("led {0} prog {1}".format(self.up, self.pfw))
- syslog.syslog(syslog.LOG_INFO, "Load Led({0}) program firmware".format(self.up))
-
- def write_port_data(self, addr, data):
- BCM_SHELL.cmd("setreg CMIC_LEDUP{0}_DATA_RAM({1}) {2}".format(self.up, addr, data))
- #syslog.syslog(syslog.LOG_DEBUG, "Write Led({0}) data_ram({1}): {2}".format(self.up, addr, data))
-
- def read_data_ram(self, offset):
- return_string = BCM_SHELL.run("getreg CMIC_LEDUP{0}_DATA_RAM({1})".format(self.up, offset))
- for line in return_string.split("\n"):
- re_obj = re.search(r"\.+)\>",line)
+class Port():
+
+ port_num = None
+ name = None
+ bcm_id = None
+ led_up = None
+ s_addr = None
+ write2_up = None
+ led_index = None
+ link_status = None
+ speed = None
+
+ def write_data_ram(self, data):
+ BCM_SHELL.cmd("setreg CMIC_LEDUP{0}_DATA_RAM({1}) {2}".format(self.write2_up, self.led_index, data))
+
+ def read_data_ram(self):
+ r_string = BCM_SHELL.run("getreg CMIC_LEDUP{0}_DATA_RAM({1})".format(self.led_up, self.s_addr))
+ for line in r_string.split("\n"):
+ re_obj = re.search(r"\.+)\>", line)
if re_obj is not None:
- #syslog.syslog(syslog.LOG_DEBUG, "Read Led({0}) data_ram({1}): {2}".format(self.up, offset, re_obj.group("data")))
+ #syslog.syslog(syslog.LOG_DEBUG, "Read Led({0}) data_ram({1}): {2}".format(self.up, addr, re_obj.group("data")))
return int(re_obj.group("data"), 16)
- return None
# =====================================================================
# Function
# =====================================================================
-def _remap_registers():
+def _remap_registers(fp):
- fp = open('/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/led_proc_init.soc', "r")
content = fp.readlines()
fp.close()
err = False
@@ -125,60 +102,13 @@ def _remap_registers():
syslog.syslog(syslog.LOG_ERR, "remap register abnormal: {0}".format(str(e)))
if not err:
- pass
- #syslog.syslog(syslog.LOG_DEBUG, "remap Led registers successfully")
-
-
-
-def _update_port_list():
-
- global PORT_LIST
- PORT_LIST = []
- number = 0
- count = 0
-
- content = BCM_SHELL.run("ps")
- for line in content.split("\n"):
- re_obj = re.search(r"(?P(xe|ce)\d+)\(\s*(?P\d+)\)\s+(?P(up|down|!ena)).+\s+(?P\d+)G",line)
- if re_obj is not None:
- if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
- PORT_LIST.append({"port_id":number, "name":re_obj.group("port_name"), "bcm_id":int(re_obj.group("bcm_id")), "link":re_obj.group("link"), "speed":int(re_obj.group("speed"))})
- number += 1
-
- content = BCM_SHELL.run("led status")
- for line in content.split("\n"):
- re_obj = re.search(r"(?P\d+).+(?P\d)\:(?P\d+)",line)
- if re_obj is not None:
- if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
- PORT_LIST[count]["led_up"] = int(re_obj.group("led_up"))
- PORT_LIST[count]["offset"] = int(re_obj.group("offset"))
- count += 1
-
- if number is not count:
- PORT_LIST = []
- syslog.syslog(syslog.LOG_ERR, "The amount of port is not match")
- else:
- pass
- #syslog.syslog(syslog.LOG_DEBUG, "update port list successfully")
-
-
-
-def _lookup_led_index(p):
-
- index = 0
- for port in PORT_LIST:
- if p["bcm_id"] == port["bcm_id"]:
- break
- if p["led_up"] == port["led_up"]:
- index += 1
- return index + PORT_DATA_OFFSET_ADDR
+ syslog.syslog(syslog.LOG_INFO, "remap Led registers successfully")
-def _led_init():
+def _board_init():
global BOARD_TPYE
- global AMOUNT_LED_UP
global BIT_LINK
global BIT_FAULT
global BIT_TX
@@ -193,24 +123,29 @@ def _led_init():
cmd = "uname -n"
platform = os.popen(cmd).read()
- if platform.rstrip() == INV_REDWOOD:
+ if platform.rstrip() == INV_MAGNOLIA:
+ BOARD_TPYE = "inventec_d6254qs"
+ BIT_RX = 1<<0 #0x01
+ BIT_TX = 1<<1 #0x02
+ BIT_SPEED1 = 1<<4 #0x10
+ BIT_LINK = 1<<7 #0x80
+ fp = open('/usr/share/sonic/device/x86_64-inventec_d6254qs-r0/led_proc_init.soc', "r")
+ _remap_registers(fp)
+
+ elif platform.rstrip() == INV_REDWOOD:
BOARD_TPYE = "inventec_d7032q28b"
- AMOUNT_LED_UP = 2
BIT_RX = 1<<0 #0x01
BIT_TX = 1<<1 #0x02
BIT_SPEED0 = 1<<3 #0x08
BIT_SPEED1 = 1<<4 #0x10
BIT_FAULT = 1<<6 #0x40
BIT_LINK = 1<<7 #0x80
- TOTAL_SCAN_BITS = 32*1*4
- SYNC_S = 15
- SYNC_P = 3
EAGLE_CORE = [66, 100]
- _remap_registers()
+ fp = open('/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/led_proc_init.soc', "r")
+ _remap_registers(fp)
elif platform.rstrip() == INV_CYPRESS:
BOARD_TPYE = "inventec_d7054q28b"
- AMOUNT_LED_UP = 2
BIT_LINK = 1<<0 #0x01
BIT_FAULT = 1<<1 #0x02
BIT_SPEED0 = 1<<2 #0x04
@@ -218,97 +153,220 @@ def _led_init():
elif platform.rstrip() == INV_SEQUOIA:
BOARD_TPYE = "inventec_d7264q28b"
- AMOUNT_LED_UP = 4
+
+ elif platform.rstrip() == INV_MAPLE:
+ BOARD_TPYE = "inventec_d6556"
+ fp = open('/usr/share/sonic/device/x86_64-inventec_d6556-r0/led_proc_init.soc', "r")
+ _remap_registers(fp)
+ #led process: m0 led process that is controlled by linkscan_led_fw.bin and custom_led.bin
+ syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE))
+ exit(0)
else:
BOARD_TPYE = "not found"
+ syslog.syslog(syslog.LOG_ERR, "Found device: {0}".format(BOARD_TPYE))
+ exit(0)
- syslog.syslog(syslog.LOG_INFO, "Device: {0}".format(BOARD_TPYE))
- #syslog.syslog(syslog.LOG_DEBUG, "led_amount: {0}".format(AMOUNT_LED_UP))
+ syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE))
-if __name__ == "__main__":
+def _lookup_led_index(p):
+
+ index = 0
+ if BOARD_TPYE == "inventec_d6254qs":
+ if 0 <= p.port_num <= 47:
+ index = p.port_num + (p.port_num / 4)
+ p.write2_up = 0
+ elif 48 <= p.port_num <= 71:
+ index = p.port_num - 48
+ p.write2_up = 1
+ if p.led_up == 0:
+ p.s_addr = p.port_num * 2
+ elif p.led_up == 1:
+ p.s_addr = (p.port_num - 36) * 2
+
+ elif BOARD_TPYE == "inventec_d7032q28b":
+ p.write2_up = 0
+ index = p.port_num
+ if 0 <= p.port_num <= 7:
+ p.s_addr = p.port_num * 8
+ elif 8 <= p.port_num <= 23:
+ p.s_addr = (p.port_num - 8) * 8
+ elif 24 <= p.port_num <= 31:
+ p.s_addr = (p.port_num - 16) * 8
+
+ else:
+ p.write2_up = p.led_up
+ for port in PORT_LIST:
+ if p.bcm_id == port.bcm_id:
+ break
+ if p.led_up == port.led_up:
+ index += 1
+
+ return PORT_DATA_OFFSET_ADDR + index
+
+
+def _update_port_list(only_update):
+
+ global PORT_LIST
+ number = 0
+ count = 0
+
+ content = BCM_SHELL.run("ps")
+ for line in content.split("\n"):
+ re_obj = re.search(r"(?P(xe|ce)\d+)\(\s*(?P\d+)\)\s+(?P(up|down|!ena)).+\s+(?P\d+)G", line)
+ if re_obj is not None:
+ if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
+ if only_update:
+ PORT_LIST[number].link_status = re_obj.group("link")
+ else:
+ # create port object while first time
+ port_obj = Port()
+ port_obj.port_num = number
+ port_obj.name = re_obj.group("port_name")
+ port_obj.bcm_id = int(re_obj.group("bcm_id"))
+ port_obj.link_status = re_obj.group("link")
+ port_obj.speed = int(re_obj.group("speed"))
+ PORT_LIST.append(port_obj)
+ number += 1
+
+ if not only_update:
+ content = BCM_SHELL.run("led status")
+ for line in content.split("\n"):
+ re_obj = re.search(r"(?P\d+).+(?P\d)\:", line)
+ if re_obj is not None:
+ if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
+ PORT_LIST[count].led_up = int(re_obj.group("led_up"))
+ PORT_LIST[count].led_index = _lookup_led_index(PORT_LIST[count])
+ count += 1
+
+ if number is not count:
+ PORT_LIST = []
+ syslog.syslog(syslog.LOG_ERR, "The amount of port is not match")
+
- waitSyncd = True
- retryCount = 0
- syslog.openlog("led_proc", syslog.LOG_PID, facility=syslog.LOG_DAEMON)
+
+def sync_bcmsh_socket():
+
+ global BCM_SHELL
+ global SHELL_READY
+ waitSyncd = True
+ retryCount = 0
while waitSyncd:
+ time.sleep(10)
try:
BCM_SHELL = bcmshell()
+ BCM_SHELL.run("Echo")
waitSyncd = False
except Exception, e:
- syslog.syslog(syslog.LOG_WARNING, "{0}, Retry times({1})".format(str(e),retryCount))
+ print "{0}, Retry times({1})".format(str(e),retryCount)
+ #syslog.syslog(syslog.LOG_DEBUG, "{0}, Retry times({1})".format(str(e),retryCount))
retryCount += 1
- time.sleep(5)
-
-
- _led_init()
- led_obj = []
- for idx in range(AMOUNT_LED_UP):
- led_obj.append(Led(idx, ""))
- #syslog.syslog(syslog.LOG_DEBUG, "create object led({0}) successfully".format(idx))
-
- if BOARD_TPYE == "inventec_d7032q28b":
- led_obj[idx].write_port_data(PORT_DATA_START_ADDR, PORT_DATA_OFFSET_ADDR)
- led_obj[idx].write_port_data(TOTAL_SCAN_BITS_ADDR, TOTAL_SCAN_BITS)
- led_obj[idx].write_port_data(SYNC_START_LEN_ADDR, SYNC_S)
- led_obj[idx].write_port_data(SYNC_STOP_LEN_ADDR, SYNC_P)
-
-
- reset_sec = 2
- count_down = 0
- queue_active = []
- port_data = None
- while True:
- if count_down == 0:
- queue_active = []
- _update_port_list()
- for port in PORT_LIST:
- if port["link"] == "up":
- queue_active.append(port)
- else:
- port_data = 0
- # redwood bit streaming for CPLD decode is only use led up0
- led_obj[0].write_port_data(PORT_DATA_OFFSET_ADDR + port["port_id"], port_data)
- count_down = reset_sec
- else:
- for port in queue_active:
- port_data = 0
-
- if BOARD_TPYE == "inventec_d7032q28b":
- port_data |= BIT_LINK
- addr = 2*(port["offset"]-1)
- byte1 = led_obj[port["led_up"]].read_data_ram(addr)
- byte2 = led_obj[port["led_up"]].read_data_ram(addr+1)
- if byte1&STATUS_RX:
- port_data |= BIT_RX
- if byte1&STATUS_TX:
- port_data |= BIT_TX
- if port["speed"] == SPEED_100G:
- port_data |= BIT_SPEED0
- port_data |= BIT_SPEED1
- elif port["speed"] == SPEED_40G:
- port_data |= BIT_SPEED1
- elif port["speed"] == SPEED_25G:
- port_data |= BIT_SPEED0
+
+ syslog.syslog(syslog.LOG_INFO, "bcmshell socket create successfully")
+
+ if SHELL_READY is False:
+ SHELL_READY = True
+ return
+ elif SHELL_READY is True:
+ update_led_status()
+
+
+
+def update_led_status():
+
+ led_thread = True # True/False (gate to turn on/off)
+ reset_sec = 2
+ count_down = 0
+ queue_active = []
+ port_data = None
+ s_byte = None
+
+
+ # thread for keeping update port status in data ram
+ while led_thread:
+ try:
+ if count_down == 0:
+ queue_active = []
+ _update_port_list(1)
+ for port in PORT_LIST:
+ if port.link_status == "up":
+ queue_active.append(port)
else:
- pass
+ port_data = 0
+ port.write_data_ram(port_data)
+ count_down = reset_sec
+ else:
+ for port in queue_active:
+ port_data = 0
- # redwood bit streaming for CPLD decode is only use led up0
- led_obj[0].write_port_data(PORT_DATA_OFFSET_ADDR + port["port_id"], port_data)
- continue
+ if BOARD_TPYE == "inventec_d6254qs":
+ s_byte = port.read_data_ram()
+ if s_byte&STATUS_RX:
+ port_data |= BIT_RX
+ if s_byte&STATUS_TX:
+ port_data |= BIT_TX
+ port_data |= BIT_LINK
+
+ elif BOARD_TPYE == "inventec_d7032q28b":
+ s_byte = port.read_data_ram()
+ if s_byte&STATUS_RX:
+ port_data |= BIT_RX
+ if s_byte&STATUS_TX:
+ port_data |= BIT_TX
+ if port.speed == SPEED_100G:
+ port_data |= BIT_SPEED0
+ port_data |= BIT_SPEED1
+ elif port.speed == SPEED_40G:
+ port_data |= BIT_SPEED1
+ elif port.speed == SPEED_25G:
+ port_data |= BIT_SPEED0
+ else:
+ pass
+ port_data |= BIT_LINK
+
+ elif BOARD_TPYE == "inventec_d7054q28b":
+ if port.speed != SPEED_100G and port.speed != SPEED_25G:
+ port_data |= BIT_SPEED0
+
+ # write data to update data ram for specific port
+ port.write_data_ram(port_data)
+
+ time.sleep(0.5)
+ count_down -= 1
- elif BOARD_TPYE == "inventec_d7054q28b":
- if port["speed"] != SPEED_100G and port["speed"] != SPEED_25G:
- port_data |= BIT_SPEED0
+ except Exception, e:
+ syslog.syslog(syslog.LOG_WARNING, "{0}".format(str(e)))
+ sync_bcmsh_socket()
- led_index = _lookup_led_index(port)
- led_obj[port["led_up"]].write_port_data(led_index, port_data)
- time.sleep(0.5)
- count_down -= 1
- syslog.closelog()
+def debug_print():
+
+ for port in PORT_LIST:
+ output = ""
+ output += "name:{0} | ".format(port.name)
+ output += "port_num:{0} | ".format(port.port_num)
+ output += "bcm_id:{0} | ".format(port.bcm_id)
+ output += "link_status:{0} | ".format(port.link_status)
+ output += "speed:{0} | ".format(port.speed)
+ output += "led_up:{0} | ".format(port.led_up)
+ output += "s_addr:{0} | ".format(port.s_addr)
+ output += "write2_up:{0} | ".format(port.write2_up)
+ output += "led_index:{0} | ".format(port.led_index)
+ print output
+
+if __name__ == "__main__":
+
+ syslog.openlog("led_proc", syslog.LOG_PID, facility=syslog.LOG_DAEMON)
+
+ sync_bcmsh_socket()
+ _board_init()
+ _update_port_list(0)
+ #debug_print()
+ update_led_status()
+
+ syslog.closelog()
diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py
new file mode 100755
index 000000000000..f1e7f7fece77
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/platform_status.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+import os
+import socket
+from collections import OrderedDict
+
+# Purpose: Shutdown DUT upon receiving thermaltrip event from kernel (inv_pthread)
+
+NETLINK_KOBJECT_UEVENT = 15
+
+class KernelEventMonitor(object):
+
+ def __init__(self):
+ self.received_events = OrderedDict()
+ self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)
+
+ def start(self):
+ self.socket.bind((os.getpid(), -1))
+
+ def stop(self):
+ self.socket.close()
+
+ def __enter__(self):
+ self.start()
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.stop()
+
+ def __iter__(self):
+ while True:
+ for item in monitor.next_events():
+ yield item
+
+ def next_events(self):
+ data = self.socket.recv(16384)
+ event = {}
+ for item in data.split(b'\x00'):
+ if not item:
+ #check if we have an event and if we already received it
+ if event and event['SEQNUM'] not in self.received_events:
+ self.received_events[event['SEQNUM']] = None
+ if (len(self.received_events) > 100):
+ self.received_events.popitem(last=False)
+ yield event
+ event = {}
+ else:
+ try:
+ k, v = item.split(b'=', 1)
+ event[k.decode('ascii')] = v.decode('ascii')
+ except ValueError:
+ pass
+
+if __name__ == '__main__':
+ with KernelEventMonitor() as monitor:
+ for event in monitor:
+ if event['SUBSYSTEM'] == 'platform_status':
+ print('subsystem is platform_status')
+
+ # Receive thermaltrip event
+ if event['ACTION'] == 'remove' and event['DEVPATH'] == '/kernel/platform_status/fan':
+ os.system("shutdown -h now")
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py b/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py
index 6546a4e44ca0..9e4a44c167fe 100755
--- a/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py
+++ b/platform/broadcom/sonic-platform-modules-inventec/common/utils/transceiver_monitor.py
@@ -1,5 +1,10 @@
#!/usr/bin/env python
#
+# Copyright (C) 2018 Inventec, Inc.
+#
+# Editor: James Huang ( Huang.James@inventec.com )
+#
+#
"""
Usage: %(scriptName)s [options] command object
@@ -32,6 +37,8 @@
INV_REDWOOD_PLATFORM = "SONiC-Inventec-d7032-100"
INV_CYPRESS_PLATFORM = "SONiC-Inventec-d7054"
INV_SEQUOIA_PLATFORM = "SONiC-Inventec-d7264"
+INV_MAPLE_PLATFORM = "SONiC-Inventec-d6556"
+INV_MAGNOLIA_PLATFORM = "SONiC-Inventec-d6254qs"
transceiver_type_dict = {
"FCBG110SD1C03": "SR",
@@ -76,7 +83,29 @@
"L0HSF006-SD-R": "KR",
"L0HSF007-SD-R": "KR",
"L0HSF008-SD-R": "KR",
- "L0HQF009-SD-R": "KR4"
+ "L0HQF009-SD-R": "KR4",
+ "FSPP-H7-M85-X3D": "SR",
+ "PT0-M3-4D33K-C2": "SR",
+ "RTXM228-551": "SR",
+ "RTXM330-003": "SR",
+ "RTXM330-030": "SR",
+ "MFA2P10-A005": "SR",
+ "QAB-OA03MC": "SR4",
+ "QAB-OA05MC": "SR4",
+ "RTXM320-571": "SR4",
+ "AFBR-89CDDZ": "SR4",
+ "RTXM420-550": "SR4",
+ "MMA1B00-C100D": "SR4",
+ "RTXM420-551": "SR4",
+ "E04025QTXA000": "SR4",
+ "LQ210PR-Oxxx": "SR4",
+ "TR-FC13L-N00": "SR4",
+ "SPQ-CE-LR-CDFL": "SR4",
+ "FIM37700/170": "SR4",
+ "FCBN425QE1C03": "SR4",
+ "TQS-Q14H8-XCAXX": "SR4",
+ "FPD-203R008-10/3": "SR4",
+ "LTA8531-PC+": "SR4"
}
initial_command = []
@@ -107,8 +136,9 @@ def get_port_to_bcm_mapping(self):
else:
return self.port_to_bcm_mapping
- def show_port_to_bcm_mapping(self):
- print self.port_to_bcm_mapping
+ def show_port_to_bcm_mapping(self):
+ for key,value in self.port_to_bcm_mapping.iteritems():
+ print "{0}---{1}".format(key, value)
def get_eagle_port(self):
return self.eagle_list
@@ -122,6 +152,8 @@ def parsing_eagle_port(self):
self.eagle_list = [66,100]
elif name == INV_SEQUOIA_PLATFORM:
self.eagle_list = [66,100]
+ elif name == INV_MAPLE_PLATFORM:
+ self.eagle_list = [66,130]
else:
self.eagle_list = []
@@ -129,7 +161,8 @@ def get_sal_config_list(self):
return self.sal_config_list
def show_sal_config_list(self):
- print self.sal_config_list
+ for key,value in self.sal_config_list.iteritems():
+ print "{0}---{1}".format(key, value)
def initial_sal_config_list( self ):
content = self.run("config")
@@ -164,7 +197,8 @@ def get_transceiver_port_mapping(self):
return self.transceiver_port_mapping
def show_transceiver_port_mapping(self):
- print self.transceiver_port_mapping
+ for key,value in self.transceiver_port_mapping.iteritems():
+ print "{0}---{1}".format(key, value)
def get_bcm_port_name(self, index):
if self.transceiver_port_mapping.has_key(index) and bcm_obj.get_sal_config_list().has_key(self.transceiver_port_mapping[index]["bcm"]):
@@ -179,7 +213,8 @@ def get_port_to_i2c_mapping(self):
return self.port_to_i2c_mapping
def show_port_to_i2c_mapping(self):
- print self.port_to_i2c_mapping
+ for key,value in self.port_to_i2c_mapping.iteritems():
+ print "{0}---{1}".format(key, value)
def get_eeprom_partNum(self, portNum):
tempdict = dict()
@@ -210,12 +245,12 @@ def get_transceiver_type(self, pn ):
def set_transceiver_type( self, portNum, pn ):
type = self.get_transceiver_type( pn )
if type is not None:
- if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM:
+ if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM or bcm_obj.get_platform() == INV_MAPLE_PLATFORM :
speed = bcm_obj.get_sal_config_list()[self.transceiver_port_mapping[portNum]["bcm"]]["speed"]
bcm_obj.execute_command( "port %s if=%s speed=%d" % ( self.get_bcm_port_name(portNum), type, speed ) )
else:
bcm_obj.execute_command( "port %s if=%s" % ( self.get_bcm_port_name(portNum), type ) )
- #print "Detecting port {0} need to change interface type {1} ({2})".format(self.get_bcm_port_name(portNum), type, self.get_transceiver_port_mapping()[portNum]["pn"])
+ print "Detecting port {0}({1}) need to change interface type {2} ({3})".format( self.get_bcm_port_name(portNum), portNum, type, self.get_transceiver_port_mapping()[portNum]["pn"])
log_message("Detecting port {0} need to change interface type {1} ({2})".format(self.get_bcm_port_name(portNum), type, self.get_transceiver_port_mapping()[portNum]["pn"]) )
def initial_transceiver_port_mapping(self):
@@ -229,57 +264,90 @@ def set_power_mode_for_QSFP(self):
for index in self.get_port_to_i2c_mapping().keys():
if index >= self.qsfp_port_start and index <= self.qsfp_port_end :
self.set_low_power_mode(index, False)
+ else:
+ # To set tx_disable
+ self.set_tx_disable(index)
-def main():
- try:
- global DEBUG
- global transceiver_obj
- global bcm_obj
-
- initalNotOK = True
- retestCount = 0
- while initalNotOK :
- try:
- transceiver_obj = TransceiverUtil()
- bcm_obj = BCMUtil()
- initalNotOK = False
- except Exception, e:
- log_message("Exception. The warning is {0}, Retry again ({1})".format(str(e),retestCount) )
- retestCount = retestCount + 1
- time.sleep(5)
-
- log_message( "Object initialed successfully" )
+ def set_tx_disable(self, port_num):
+ if port_num >= self.qsfp_port_start and port_num <= self.qsfp_port_end :
+ pass
+ else:
+ try:
+ tx_file = open("/sys/class/swps/port"+str(port_num)+"/tx_disable", "r+")
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ reg_value = int(tx_file.readline().rstrip())
+
+ # always set 0 to tx_disable field
+ if reg_value == 1 :
+ reg_value = 0
+ tx_file.write(hex(reg_value))
+ tx_file.close()
- options, args = getopt.getopt(sys.argv[1:], 'hd', ['help',
- 'debug'
- ])
- for opt, arg in options:
- if opt in ('-h', '--help'):
- show_help()
- elif opt in ('-d', '--debug'):
- DEBUG = True
- logging.basicConfig(level=logging.INFO)
- else:
- logging.info("no option")
-
- # Before loop, You could execute specific command to initial chip
- for cmd_index in initial_command :
- bcm_obj.execute_command(cmd_index)
-
- # Initial the sal config list
- bcm_obj.parsing_eagle_port()
- bcm_obj.initial_sal_config_list()
- bcm_obj.parsing_port_list()
- # bcm_obj.show_port_to_bcm_mapping()
- # bcm_obj.show_sal_config_list()
- # Initial the transceiver_obj
- transceiver_obj.initial_transceiver_port_mapping()
- # transceiver_obj.show_transceiver_port_mapping()
-
- transceiver_obj.set_power_mode_for_QSFP()
+def main():
- while 1 :
+ global DEBUG
+ global transceiver_obj
+ global bcm_obj
+
+ initalNotOK = True
+ retestCount = 0
+ while initalNotOK :
+ try:
+ transceiver_obj = TransceiverUtil()
+ bcm_obj = BCMUtil()
+ initalNotOK = False
+ except Exception, e:
+ log_message("Exception. The warning is {0}, Retry again ({1})".format(str(e),retestCount) )
+ retestCount = retestCount + 1
+ time.sleep(5)
+
+ log_message( "Object initialed successfully" )
+ options, args = getopt.getopt(sys.argv[1:], 'hd', ['help',
+ 'debug'
+ ])
+ for opt, arg in options:
+ if opt in ('-h', '--help'):
+ show_help()
+ elif opt in ('-d', '--debug'):
+ DEBUG = True
+ logging.basicConfig(level=logging.INFO)
+ else:
+ logging.info("no option")
+
+ initalNotOK = True
+ while initalNotOK :
+ try :
+ # Before loop, You could execute specific command to initial chip
+ for cmd_index in initial_command :
+ bcm_obj.execute_command(cmd_index)
+
+ # Initial the sal config list
+ bcm_obj.parsing_eagle_port()
+ bcm_obj.initial_sal_config_list()
+ # bcm_obj.show_sal_config_list()
+ bcm_obj.parsing_port_list()
+ #bcm_obj.show_port_to_bcm_mapping()
+ #bcm_obj.show_sal_config_list()
+ # transceiver_obj.show_port_to_i2c_mapping()
+
+ # Initial the transceiver_obj
+ transceiver_obj.initial_transceiver_port_mapping()
+ # transceiver_obj.show_transceiver_port_mapping()
+
+ initalNotOK = False
+ except Exception, e:
+ log_message("Exception. The warning is {0}".format(str(e)) )
+ time.sleep(5)
+
+ # Improve the power mode for QSFP ports
+ transceiver_obj.set_power_mode_for_QSFP()
+
+ while 1 :
+ try:
if bcm_obj.get_platform() == INV_SEQUOIA_PLATFORM:
bcm_obj.parsing_port_list()
for index in transceiver_obj.get_port_to_i2c_mapping().keys():
@@ -287,15 +355,17 @@ def main():
value = transceiver_obj.get_eeprom_partNum_from_parser_eeprom_dict(info)
if transceiver_obj.get_transceiver_port_mapping().has_key(index) is not False and transceiver_obj.get_transceiver_port_mapping()[index]["pn"] <> value:
transceiver_obj.get_transceiver_port_mapping()[index]["pn"] = value
- transceiver_obj.set_transceiver_type(index,value)
- #transceiver_obj.show_transceiver_port_mapping()
- time.sleep(1)
+ transceiver_obj.set_transceiver_type(index,value)
+ transceiver_obj.set_tx_disable(index)
+ #transceiver_obj.show_transceiver_port_mapping()
+ # transceiver_obj.show_transceiver_port_mapping()
+ except Exception, e:
+ log_message("Exception. The warning is {0}".format(str(e)) )
+ time.sleep(1)
- except (Exception, KeyboardInterrupt) as e:
- log_message("Terminating this python daemon ({0})".format(e))
- syslog.closelog()
- del transceiver_obj
- del bcm_obj
+ syslog.closelog()
+ del transceiver_obj
+ del bcm_obj
if __name__ == "__main__":
main()
@@ -303,3 +373,6 @@ def main():
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile
new file mode 100644
index 000000000000..13fc34c230c5
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/Makefile
@@ -0,0 +1,7 @@
+obj-m += inv_cpld.o inv_psoc.o
+obj-m += inv_platform.o
+obj-m += inv_eeprom.o
+obj-m += swps.o
+obj-m += inv_pthread.o
+swps-objs := inv_swps.o io_expander.o transceiver.o
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c
new file mode 100644
index 000000000000..683ffa0ff3ce
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_cpld.c
@@ -0,0 +1,415 @@
+/*
+ * 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#include "I2CHostCommunication.h"
+
+#define USE_SMBUS 1
+
+/* definition */
+#define CPLD_INFO_OFFSET 0x00
+#define CPLD_PSU_OFFSET 0x08
+#define CPLD_LED_OFFSET 0x0E
+#define CPLD_LED_STATU_OFFSET 0x0D
+#define CPLD_CTL_OFFSET 0x0C
+
+
+
+/* Each client has this additional data */
+struct cpld_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+};
+
+/*-----------------------------------------------------------------------*/
+
+static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg[0].buf = msgbuf;
+ msg[0].len = 1;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = count;
+
+ status = i2c_transfer(client->adapter, msg, 2);
+
+ if(status == 2)
+ status = count;
+
+ return status;
+#endif
+}
+
+static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg.flags = 0;
+
+ /* msg.buf is u8 and casts will mask the values */
+ msg.buf = writebuf;
+
+ msg.buf[i++] = offset;
+ memcpy(&msg.buf[i], buf, count);
+ msg.len = i + count;
+
+ status = i2c_transfer(client->adapter, &msg, 1);
+ if (status == 1)
+ status = count;
+
+ return status;
+#endif
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* sysfs attributes for hwmon */
+
+static ssize_t show_info(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 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);
+ u8 b[4];
+
+ memset(b, 0, 4);
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4);
+ mutex_unlock(&data->update_lock);
+
+ if(status != 4) return sprintf(buf, "read cpld info fail\n");
+
+ status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/
+ status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf);
+ status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf);
+
+ return strlen(buf);
+}
+
+
+static ssize_t show_ctl(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 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);
+ u8 b[1];
+
+ mutex_lock(&data->update_lock);
+
+ status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1);
+
+ mutex_unlock(&data->update_lock);
+
+ if(status != 1) return sprintf(buf, "read cpld ctl fail\n");
+
+
+ status = sprintf (buf, "0x%X\n", b[0]);
+
+ return strlen(buf);
+}
+
+static ssize_t set_ctl(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 byte;
+
+ u8 temp = simple_strtol(buf, NULL, 10);
+
+ mutex_lock(&data->update_lock);
+ cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1);
+ if(temp) byte |= (1<<0);
+ else byte &= ~(1<<0);
+ cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+
+static char* led_str[] = {
+ "OFF", //000
+ "0.5 Hz", //001
+ "1 Hz", //010
+ "2 Hz", //011
+ "NA", //100
+ "NA", //101
+ "NA", //110
+ "ON", //111
+};
+
+static ssize_t show_led(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 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);
+ u8 byte;
+ int shift = (attr->index == 0)?3:0;
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET);
+
+ byte = (byte >> shift) & 0x7;
+
+ /*
+ 0: off
+ 1: 0.5hz
+ 2: 1 hz
+ 3: 2 hz
+ 4~6: not define
+ 7: on
+ */
+
+ status = sprintf (buf, "%d: %s\n", byte, led_str[byte]);
+
+ return strlen(buf);
+}
+
+static ssize_t set_led(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ 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;
+ int shift = (attr->index == 0)?3:0;
+
+ temp &= 0x7;
+ //validate temp value: 0,1,2,3,7, TBD
+
+ mutex_lock(&data->update_lock);
+ cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
+ byte &= ~(0x7<update_lock);
+
+ return count;
+}
+
+/*
+CPLD report the PSU0 status
+000 = PSU normal operation
+100 = PSU fault
+010 = PSU unpowered
+111 = PSU not installed
+
+7 6 | 5 4 3 | 2 1 0
+----------------------
+ | psu0 | psu1
+*/
+static char* psu_str[] = {
+ "normal", //000
+ "NA", //001
+ "unpowered", //010
+ "NA", //011
+ "fault", //100
+ "NA", //101
+ "NA", //110
+ "not installed", //111
+};
+
+static ssize_t show_psu(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 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);
+ u8 byte;
+ int shift = (attr->index == 1)?0:3;
+
+ mutex_lock(&data->update_lock);
+ status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ byte = (byte >> shift) & 0x7;
+
+ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
+
+ return strlen(buf);
+}
+
+
+static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0);
+static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0);
+
+static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0);
+static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1);
+
+static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0);
+static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1);
+
+static struct attribute *cpld_attributes[] = {
+ //info
+ &sensor_dev_attr_info.dev_attr.attr,
+ &sensor_dev_attr_ctl.dev_attr.attr,
+
+ &sensor_dev_attr_grn_led.dev_attr.attr,
+ &sensor_dev_attr_red_led.dev_attr.attr,
+
+ &sensor_dev_attr_psu0.dev_attr.attr,
+ &sensor_dev_attr_psu1.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;
+
+ printk("+%s\n", __func__);
+
+ 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;
+ }
+
+ 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);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &cpld_group);
+ i2c_set_clientdata(client, 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("eddie.lan ");
+MODULE_DESCRIPTION("inv cpld driver");
+MODULE_LICENSE("GPL");
+
+module_init(inv_cpld_init);
+module_exit(inv_cpld_exit);
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_eeprom.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_eeprom.c
new file mode 100644
index 000000000000..3d13f3b04719
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/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
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+/* 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 D7054 Mother Board EEPROM driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c
new file mode 100644
index 000000000000..a8a9a3c3df79
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.c
@@ -0,0 +1,280 @@
+/*
+ * 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
+#include
+#include
+#include
+#include
+#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 :%d :%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_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 :%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/d6254qs/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h
new file mode 100644
index 000000000000..687a11b4e5be
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_mux.h
@@ -0,0 +1,45 @@
+/*
+ * 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_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/d6254qs/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c
new file mode 100644
index 000000000000..e69b526f4555
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_platform.c
@@ -0,0 +1,243 @@
+/*
+ * 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
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+struct inv_i2c_board_info {
+ int ch;
+ int size;
+ struct i2c_board_info *board_info;
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+static struct pca954x_platform_mode mux_modes_0[] = {
+ {.adap_id = 2,}, {.adap_id = 3,},
+ {.adap_id = 4,}, {.adap_id = 5,},
+ {.adap_id = 6,}, {.adap_id = 7,},
+ {.adap_id = 8,}, {.adap_id = 9,},
+};
+static struct pca954x_platform_mode mux_modes_0_0[] = {
+ {.adap_id = 10,}, {.adap_id = 11,},
+ {.adap_id = 12,}, {.adap_id = 13,},
+ {.adap_id = 14,}, {.adap_id = 15,},
+ {.adap_id = 16,}, {.adap_id = 17,},
+};
+
+static struct pca954x_platform_mode mux_modes_0_1[] = {
+ {.adap_id = 18,}, {.adap_id = 19,},
+ {.adap_id = 20,}, {.adap_id = 21,},
+ {.adap_id = 22,}, {.adap_id = 23,},
+ {.adap_id = 24,}, {.adap_id = 25,},
+};
+
+static struct pca954x_platform_mode mux_modes_0_2[] = {
+ {.adap_id = 26,}, {.adap_id = 27,},
+ {.adap_id = 28,}, {.adap_id = 29,},
+ {.adap_id = 30,}, {.adap_id = 31,},
+ {.adap_id = 32,}, {.adap_id = 33,},
+};
+
+static struct pca954x_platform_mode mux_modes_0_3[] = {
+ {.adap_id = 34,}, {.adap_id = 35,},
+ {.adap_id = 36,}, {.adap_id = 37,},
+ {.adap_id = 38,}, {.adap_id = 39,},
+ {.adap_id = 40,}, {.adap_id = 41,},
+};
+
+static struct pca954x_platform_mode mux_modes_0_4[] = {
+ {.adap_id = 42,}, {.adap_id = 43,},
+ {.adap_id = 44,}, {.adap_id = 45,},
+ {.adap_id = 46,}, {.adap_id = 47,},
+ {.adap_id = 48,}, {.adap_id = 49,},
+};
+
+static struct pca954x_platform_mode mux_modes_0_5[] = {
+ {.adap_id = 50,}, {.adap_id = 51,},
+ {.adap_id = 52,}, {.adap_id = 53,},
+ {.adap_id = 54,}, {.adap_id = 55,},
+ {.adap_id = 56,}, {.adap_id = 57,},
+};
+
+static struct pca954x_platform_mode mux_modes_0_6[] = {
+ {.adap_id = 58,}, {.adap_id = 59,},
+ {.adap_id = 60,}, {.adap_id = 61,},
+ {.adap_id = 62,}, {.adap_id = 63,},
+ {.adap_id = 64,}, {.adap_id = 65,},
+};
+
+//no i2c device driver attach to mux 7
+
+
+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 xlp_i2c_device_info0[] __initdata = {
+ {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
+ {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
+ {"pca9548", 0, 0x71, &mux_data_0, 0, 0},
+};
+
+static struct i2c_board_info xlp_i2c_device_info1[] __initdata = {
+ {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
+ {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
+};
+
+static struct i2c_board_info xlp_i2c_device_info2[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0},
+};
+
+static struct i2c_board_info xlp_i2c_device_info3[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0},
+};
+
+static struct i2c_board_info xlp_i2c_device_info4[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0},
+};
+
+static struct i2c_board_info xlp_i2c_device_info5[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0},
+};
+static struct i2c_board_info xlp_i2c_device_info6[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0},
+};
+static struct i2c_board_info xlp_i2c_device_info7[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0},
+};
+static struct i2c_board_info xlp_i2c_device_info8[] __initdata = {
+ {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0},
+};
+
+
+static struct inv_i2c_board_info i2cdev_list[] = {
+ {0, ARRAY_SIZE(xlp_i2c_device_info0), xlp_i2c_device_info0 }, //smbus 0
+
+ {2, ARRAY_SIZE(xlp_i2c_device_info2), xlp_i2c_device_info2 }, //mux 0
+ {3, ARRAY_SIZE(xlp_i2c_device_info3), xlp_i2c_device_info3 }, //mux 1
+ {4, ARRAY_SIZE(xlp_i2c_device_info4), xlp_i2c_device_info4 }, //mux 2
+ {5, ARRAY_SIZE(xlp_i2c_device_info5), xlp_i2c_device_info5 }, //mux 3
+ {6, ARRAY_SIZE(xlp_i2c_device_info6), xlp_i2c_device_info6 }, //mux 4
+ {7, ARRAY_SIZE(xlp_i2c_device_info7), xlp_i2c_device_info7 }, //mux 5
+ {8, ARRAY_SIZE(xlp_i2c_device_info8), xlp_i2c_device_info8 }, //mux 6
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+static struct i2c_gpio_platform_data i2c_gpio_platdata = {
+ .scl_pin = 8,
+ .sda_pin = 9,
+
+ .udelay = 5, //5:100kHz
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+ .scl_is_output_only = 0
+};
+
+static struct platform_device magnolia_device_i2c_gpio = {
+ .name = "i2c-gpio",
+ .id = 0, // adapter number
+ .dev.platform_data = &i2c_gpio_platdata,
+};
+
+#define PLAT_MAX_I2C_CLIENTS 32
+static struct i2c_client *plat_i2c_client[PLAT_MAX_I2C_CLIENTS];
+static int num_i2c_clients = 0;
+static int plat_i2c_client_add(struct i2c_client *e)
+{
+ if (num_i2c_clients >= PLAT_MAX_I2C_CLIENTS)
+ return -1;
+
+ plat_i2c_client[num_i2c_clients] = e;
+ num_i2c_clients++;
+ return num_i2c_clients;
+}
+
+static void plat_i2c_client_remove_all(void)
+{
+ int i;
+ for (i = num_i2c_clients-1; i >= 0; i--)
+ i2c_unregister_device(plat_i2c_client[i]);
+}
+
+static int __init plat_magnolia_init(void)
+{
+ struct i2c_adapter *adap = NULL;
+ struct i2c_client *e = NULL;
+ int ret = 0;
+ int i,j;
+
+ for(i=0; i
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//#include "I2CHostCommunication.h"
+
+#define USE_SMBUS 1
+
+#define FAN_NUM 4
+#define PSU_NUM 2
+
+struct __attribute__ ((__packed__)) psoc_psu_layout {
+ u16 psu1_iin;
+ u16 psu2_iin;
+ u16 psu1_iout;
+ u16 psu2_iout;
+
+ u16 psu1_pin;
+ u16 psu2_pin;
+ u16 psu1_pout;
+ u16 psu2_pout;
+
+ u16 psu1_vin;
+ u16 psu2_vin;
+ u16 psu1_vout;
+ u16 psu2_vout;
+
+ u8 psu1_vendor[16];
+ u8 psu2_vendor[16];
+ u8 psu1_model[20];
+ u8 psu2_model[20];
+ u8 psu1_version[8];
+ u8 psu2_version[8];
+ u8 psu1_date[6];
+ u8 psu2_date[6];
+ u8 psu1_sn[20];
+ u8 psu2_sn[20];
+};
+
+struct __attribute__ ((__packed__)) psoc_layout {
+ u8 ctl; //offset: 0
+ u16 switch_temp; //offset: 1
+ u8 reserve0; //offset: 3
+
+ u8 fw_upgrade; //offset: 4
+
+ //i2c bridge
+ u8 i2c_st; //offset: 5
+ u8 i2c_ctl; //offset: 6
+ u8 i2c_addr; //offset: 7
+ u8 i2c_data[0x20]; //offset: 8
+
+ //gpo
+ u8 led_ctl; //offset: 28
+
+ u8 gpio; //offset: 29
+
+ //pwm duty
+ u8 pwm[FAN_NUM]; //offset: 2a
+ u8 pwm_psu[PSU_NUM]; //offset: 2e
+
+ //fan rpm
+ u16 fan[FAN_NUM*2]; //offset: 30
+
+ u8 reserve1[4]; //offset: 40
+
+ //gpi
+ u8 gpi_fan; //offset: 44
+
+ //psu state
+ u8 psu_state; //offset: 45
+
+ //temperature
+ u16 temp[5]; //offset: 46
+ u16 temp_psu[PSU_NUM]; //offset: 50
+
+ //version
+ u8 version[2]; //offset: 54
+
+ u8 reserve2[4]; //offset: 56
+ struct psoc_psu_layout psu_info; //offset: 5a
+};
+
+/* definition */
+/* definition */
+#define PSOC_OFF(m) offsetof(struct psoc_layout, m)
+#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m)
+
+#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp)
+#define PWM_OFFSET PSOC_OFF(pwm)
+#define THERMAL_OFFSET PSOC_OFF(temp)
+#define RPM_OFFSET PSOC_OFF(fan)
+#define DIAG_FLAG_OFFSET PSOC_OFF(ctl)
+#define FAN_LED_OFFSET PSOC_OFF(led_ctl)
+#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan)
+#define PSOC_PSU_OFFSET PSOC_OFF(psu_state)
+#define VERSION_OFFSET PSOC_OFF(version)
+#define PSU_INFO_OFFSET PSOC_OFF(psu_info)
+
+/* Each client has this additional data */
+struct psoc_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+ u32 diag;
+};
+
+/*-----------------------------------------------------------------------*/
+
+static ssize_t psoc_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg[0].buf = msgbuf;
+ msg[0].len = 1;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].buf = buf;
+ msg[1].len = count;
+
+ status = i2c_transfer(client->adapter, msg, 2);
+
+ if(status == 2)
+ status = count;
+
+ return status;
+#endif
+}
+
+static ssize_t psoc_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
+{
+#if USE_SMBUS
+ int i;
+
+ for(i=0; iaddr;
+ msg.flags = 0;
+
+ /* msg.buf is u8 and casts will mask the values */
+ msg.buf = writebuf;
+
+ msg.buf[i++] = offset;
+ memcpy(&msg.buf[i], buf, count);
+ msg.len = i + count;
+
+ status = i2c_transfer(client->adapter, &msg, 1);
+ if (status == 1)
+ status = count;
+
+ return status;
+#endif
+}
+
+#if 0
+static u32 psoc_read32(struct i2c_client *client, u8 offset)
+{
+ u32 value = 0;
+ u8 buf[4];
+
+ if( psoc_i2c_read(client, buf, offset, 4) == 4)
+ value = (buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]);
+
+ return value;
+}
+#endif
+
+static u16 psoc_read16(struct i2c_client *client, u8 offset)
+{
+ u16 value = 0;
+ u8 buf[2];
+
+ if(psoc_i2c_read(client, buf, offset, 2) == 2)
+ value = (buf[0]<<8 | buf[1]<<0);
+
+ return value;
+}
+
+static u8 psoc_read8(struct i2c_client *client, u8 offset)
+{
+ u8 value = 0;
+ u8 buf = 0;
+
+ if(psoc_i2c_read(client, &buf, offset, 1) == 1)
+ value = buf;
+
+ return value;
+}
+
+//PSOC i2c bridge regsters
+#define PSOC_I2C_STATUS 0x05
+#define PSOC_I2C_CNTRL 0x06
+#define PSOC_I2C_ADDR 0x07
+#define PSOC_I2C_DATA 0x08
+
+//status bit definition
+#define PSOC_I2C_START (1 << 0)
+#define PSOC_PMB_SEL (1 << 7)
+
+//addr bits definition
+#define PSOC_I2C_READ (1 << 0)
+
+//PMBUS registers definition
+#define PMBUS_READ_VIN (0x88)
+#define PMBUS_READ_IIN (0x89)
+#define PMBUS_READ_VOUT (0x8B)
+#define PMBUS_READ_IOUT (0x8C)
+#define PMBUS_READ_POUT (0x96)
+#define PMBUS_READ_PIN (0x97)
+
+#define PMBUS_MFR_ID (0x99)
+#define PMBUS_MFR_MODEL (0x9A)
+#define PMBUS_MFR_REVISION (0x9B)
+#define PMBUS_MFR_DATE (0x9D)
+#define PMBUS_MFR_SERIAL (0x9E)
+
+static int psoc_i2c_bridge_read(struct i2c_client *client,
+ unsigned char bus,
+ unsigned char chip,
+ char *addr, int alen,
+ unsigned char *data, int len )
+{
+ unsigned char txdata[28], rxdata[28];
+ int index, timeout;
+
+ txdata[PSOC_I2C_STATUS] = 0; /* the status */
+ txdata[PSOC_I2C_CNTRL] = ((alen & 3) << 5) | (len & 0x1f); /* the sizes */
+ txdata[PSOC_I2C_ADDR] = (chip << 1) | PSOC_I2C_READ; /* read address */
+ for(index = 0; index < alen; index++)
+ txdata[PSOC_I2C_DATA + index] = addr[index]; /* the chip address */
+ for(; index < alen+len; index++)
+ txdata[PSOC_I2C_DATA + index] = 0; /* clear the chip data */
+
+ psoc_i2c_write(client, &txdata[PSOC_I2C_CNTRL], PSOC_I2C_CNTRL, 2 + alen + len);
+
+ //delay a while ???
+ //---------------------------------------------------------------------
+ //start write
+ txdata[PSOC_I2C_STATUS] = PSOC_I2C_START | PSOC_PMB_SEL; /* the start bit for the PM bus */
+ psoc_i2c_write(client, &txdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1);
+
+ //delay a while
+ timeout = 40; //40*20==>800 ms
+ do {
+ psoc_i2c_read(client, &rxdata[PSOC_I2C_STATUS], PSOC_I2C_STATUS, 1);
+
+ //check rxdata[5] error bit(1) and complete bit(0) ,TBD
+ if((rxdata[PSOC_I2C_STATUS] & 0x2) == 0x2) {
+ //printk("i2c bridge fail!!!\n");
+ timeout = 0;
+ break;
+ }
+ if((rxdata[PSOC_I2C_STATUS] & PSOC_I2C_START) == 0) {
+ /* comand complete */
+ psoc_i2c_read(client, &rxdata[PSOC_I2C_DATA+alen], PSOC_I2C_DATA+alen, len);
+ break;
+ }
+
+ //delay
+ msleep(20);
+ } while(timeout--);
+
+ if(timeout <= 0) {
+ return -1;
+ }
+
+ //---------------------------------------------------------------------
+
+ for(index=0; index < len; index++) {
+ data[index] = rxdata[PSOC_I2C_DATA + alen + index];
+ }
+
+ return 0;
+}
+
+
+/*
+CPLD report the PSU0 status
+000 = PSU normal operation
+100 = PSU fault
+010 = PSU unpowered
+111 = PSU not installed
+
+7 6 | 5 4 3 | 2 1 0
+----------------------
+ | psu1 | psu0
+*/
+static char* psu_str[] = {
+ "normal", //000
+ "NA", //001
+ "unpowered", //010
+ "NA", //011
+ "fault", //100
+ "NA", //101
+ "NA", //110
+ "not installed", //111
+};
+
+static ssize_t show_psu_st(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u32 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 byte;
+ int shift = (attr->index == 0)?3:0;
+
+ mutex_lock(&data->update_lock);
+ status = psoc_i2c_read(client, &byte, PSOC_PSU_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ byte = (byte >> shift) & 0x7;
+
+ status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
+
+ return strlen(buf);
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* sysfs attributes for hwmon */
+
+static ssize_t show_thermal(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index * 2 + THERMAL_OFFSET;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read16(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ (s8)(status>>8) * 1000 );
+}
+
+
+static ssize_t show_pwm(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 psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index + PWM_OFFSET;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read8(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ status);
+}
+
+static ssize_t set_pwm(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index + PWM_OFFSET;
+
+ u8 pwm = simple_strtol(buf, NULL, 10);
+ if(pwm > 255) pwm = 255;
+
+ if(data->diag) {
+ mutex_lock(&data->update_lock);
+ psoc_i2c_write(client, &pwm, offset, 1);
+ mutex_unlock(&data->update_lock);
+ }
+
+ return count;
+}
+
+
+static ssize_t show_rpm(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 psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index*2 + RPM_OFFSET;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read16(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ status);
+}
+
+static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u16 temp = 0;
+
+ mutex_lock(&data->update_lock);
+ status = psoc_i2c_read(client, (u8*)&temp, SWITCH_TMP_OFFSET, 2);
+ mutex_unlock(&data->update_lock);
+
+ status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 );
+
+ return strlen(buf);
+}
+
+static ssize_t set_switch_tmp(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+
+ long temp = simple_strtol(buf, NULL, 10);
+ u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ;
+
+ //printk("set_switch_tmp temp=%d, temp2=0x%x (%x,%x)\n", temp, temp2, ( ( (temp/1000) <<8 ) & 0xFF00 ), (( (temp%1000) / 10 ) & 0xFF));
+
+ mutex_lock(&data->update_lock);
+ psoc_i2c_write(client, (u8*)&temp2, SWITCH_TMP_OFFSET, 2);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_diag(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 diag_flag = 0;
+
+ mutex_lock(&data->update_lock);
+ status = psoc_i2c_read(client, (u8*)&diag_flag, DIAG_FLAG_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ data->diag = (diag_flag & 0x80)?1:0;
+ status = sprintf (buf, "%d\n", data->diag);
+
+ return strlen(buf);
+}
+
+static ssize_t set_diag(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 value = 0;
+ u8 diag = simple_strtol(buf, NULL, 10);
+
+ diag = diag?1:0;
+ data->diag = diag;
+
+ mutex_lock(&data->update_lock);
+ psoc_i2c_read(client, (u8*)&value, DIAG_FLAG_OFFSET, 1);
+ if(diag) value |= (1<<7);
+ else value &= ~(1<<7);
+ psoc_i2c_write(client, (u8*)&value, DIAG_FLAG_OFFSET, 1);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_version(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ //struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read16(client, VERSION_OFFSET);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) );
+}
+
+
+static ssize_t show_fan_led(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 psoc_data *data = i2c_get_clientdata(client);
+ u8 bit = attr->index;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read8(client, FAN_LED_OFFSET);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n",
+ (status & (1<index;
+ u8 led_state = 0;
+
+ u8 v = simple_strtol(buf, NULL, 10);
+
+ if(data->diag) {
+ mutex_lock(&data->update_lock);
+ led_state = psoc_read8(client, FAN_LED_OFFSET);
+ if(v) led_state |= (1<update_lock);
+ }
+
+ return count;
+}
+
+static ssize_t show_value8(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 psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = attr->index;
+
+ mutex_lock(&data->update_lock);
+
+ status = psoc_read8(client, offset);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "0x%02X\n", status );
+}
+
+static long pmbus_reg2data_linear(int data, int linear16)
+{
+ s16 exponent;
+ s32 mantissa;
+ long val;
+
+ if (linear16) { /* LINEAR16 */
+ exponent = -9;
+ mantissa = (u16) data;
+ } else { /* LINEAR11 */
+ exponent = ((s16)data) >> 11;
+ exponent = ((s16)( data & 0xF800) ) >> 11;
+ mantissa = ((s32)((data & 0x7ff) << 5)) >> 5;
+ }
+
+ //printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa);
+ val = mantissa;
+
+ /* scale result to micro-units for power sensors */
+ val = val * 1000L;
+
+ if (exponent >= 0)
+ val <<= exponent;
+ else
+ val >>= -exponent;
+
+ return val;
+}
+
+static ssize_t show_psu(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 psoc_data *data = i2c_get_clientdata(client);
+ u8 reg = attr->index & 0xFF;
+ u8 len = ((attr->index & 0xFF00) >> 8);
+ u8 chip = (attr->index >> 16)? 0x59:0x58;
+ u8 bus = 1;
+ unsigned char value[2] = {0,0};;
+
+ if (len == 2)
+ {
+ mutex_lock(&data->update_lock);
+ psoc_i2c_bridge_read(client, bus, chip, ®, 1, value, 2);
+ mutex_unlock(&data->update_lock);
+
+ status = value[1]<<8 | value[0];
+ //status1 = value[1]<<8 | value[0];
+
+ return sprintf(buf, "%ld\n", pmbus_reg2data_linear(status, (reg==PMBUS_READ_VOUT)?1:0) );
+ }
+ else
+ { //len is not defined.
+ u8 tmpbuf[32];
+ mutex_lock(&data->update_lock);
+ //length of block read
+ psoc_i2c_bridge_read(client, bus, chip, ®, 1, &len, 1);
+ //data included length
+ psoc_i2c_bridge_read(client, bus, chip, ®, 1, tmpbuf, len+1);
+ mutex_unlock(&data->update_lock);
+
+ memcpy(buf, tmpbuf+1, len);
+ buf[len]='\n';
+
+ return len+1;
+ }
+}
+
+static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u16 status;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct psoc_data *data = i2c_get_clientdata(client);
+ u8 offset = (attr->index & 0xFF) + PSU_INFO_OFFSET;
+ u8 len = (attr->index >> 8)& 0xFF;
+ u8 rxbuf[21] = {0};
+ if (len == 2)
+ {
+ mutex_lock(&data->update_lock);
+ status = psoc_read16(client, offset);
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 ));
+ }
+ else
+ {
+ mutex_lock(&data->update_lock);
+ status = psoc_i2c_read(client,rxbuf,offset,len);
+ mutex_unlock(&data->update_lock);
+ return sprintf(buf, "%s \n",rxbuf);
+ }
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4);
+static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5);
+static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 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);
+static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4);
+static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5);
+
+static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0);
+static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1);
+
+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);
+static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8);
+static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9);
+
+static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0);
+static SENSOR_DEVICE_ATTR(temp6_input, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0);
+
+static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0);
+static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0);
+
+static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0);
+static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1);
+static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2);
+static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3);
+static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4);
+static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5);
+static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6);
+static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7);
+
+static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET);
+
+static SENSOR_DEVICE_ATTR(psu1_vin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VIN);
+static SENSOR_DEVICE_ATTR(psu1_vout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_VOUT);
+static SENSOR_DEVICE_ATTR(psu1_iin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IIN);
+static SENSOR_DEVICE_ATTR(psu1_iout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_IOUT);
+static SENSOR_DEVICE_ATTR(psu1_pin, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_PIN);
+static SENSOR_DEVICE_ATTR(psu1_pout, S_IRUGO, show_psu, 0, (0<<16) | (2<<8) | PMBUS_READ_POUT);
+
+static SENSOR_DEVICE_ATTR(psu1_vendor, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_ID);
+static SENSOR_DEVICE_ATTR(psu1_model, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_MODEL);
+static SENSOR_DEVICE_ATTR(psu1_version, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_REVISION);
+static SENSOR_DEVICE_ATTR(psu1_date, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_DATE);
+static SENSOR_DEVICE_ATTR(psu1_sn, S_IRUGO, show_psu, 0, (0<<16) | (0<<8) | PMBUS_MFR_SERIAL);
+
+static SENSOR_DEVICE_ATTR(psu2_vin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VIN);
+static SENSOR_DEVICE_ATTR(psu2_vout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_VOUT);
+static SENSOR_DEVICE_ATTR(psu2_iin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IIN);
+static SENSOR_DEVICE_ATTR(psu2_iout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_IOUT);
+static SENSOR_DEVICE_ATTR(psu2_pin, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_PIN);
+static SENSOR_DEVICE_ATTR(psu2_pout, S_IRUGO, show_psu, 0, (1<<16) | (2<<8) | PMBUS_READ_POUT);
+
+static SENSOR_DEVICE_ATTR(psu2_vendor, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_ID);
+static SENSOR_DEVICE_ATTR(psu2_model, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_MODEL);
+static SENSOR_DEVICE_ATTR(psu2_version, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_REVISION);
+static SENSOR_DEVICE_ATTR(psu2_date, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_DATE);
+static SENSOR_DEVICE_ATTR(psu2_sn, S_IRUGO, show_psu, 0, (1<<16) | (0<<8) | PMBUS_MFR_SERIAL);
+
+static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_vout));
+static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_iout));
+static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pin));
+static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu1_pout));
+
+
+static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_vout));
+static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_iout));
+static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pin));
+static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, (0x02<<8)|PSOC_PSU_OFF(psu2_pout));
+
+static SENSOR_DEVICE_ATTR(psoc_psu1_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu1_vendor));
+static SENSOR_DEVICE_ATTR(psoc_psu1_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_model));
+static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu1_version));
+static SENSOR_DEVICE_ATTR(psoc_psu1_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu1_date));
+static SENSOR_DEVICE_ATTR(psoc_psu1_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu1_sn));
+static SENSOR_DEVICE_ATTR(psoc_psu2_vendor, S_IRUGO, show_psu_psoc, 0, (0x10<<8)|PSOC_PSU_OFF(psu2_vendor));
+static SENSOR_DEVICE_ATTR(psoc_psu2_model, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_model));
+static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_psu_psoc, 0, (0x08<<8)|PSOC_PSU_OFF(psu2_version));
+static SENSOR_DEVICE_ATTR(psoc_psu2_date, S_IRUGO, show_psu_psoc, 0, (0x06<<8)|PSOC_PSU_OFF(psu2_date));
+static SENSOR_DEVICE_ATTR(psoc_psu2_sn, S_IRUGO, show_psu_psoc, 0, (0x14<<8)|PSOC_PSU_OFF(psu2_sn));
+
+static struct attribute *psoc_attributes[] = {
+ //thermal
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_temp2_input.dev_attr.attr,
+ &sensor_dev_attr_temp3_input.dev_attr.attr,
+ &sensor_dev_attr_temp4_input.dev_attr.attr,
+ &sensor_dev_attr_temp5_input.dev_attr.attr,
+
+ &sensor_dev_attr_thermal_psu1.dev_attr.attr,
+ &sensor_dev_attr_thermal_psu2.dev_attr.attr,
+
+
+ //pwm
+ &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,
+ &sensor_dev_attr_pwm_psu1.dev_attr.attr,
+ &sensor_dev_attr_pwm_psu2.dev_attr.attr,
+
+ //rpm
+ &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,
+
+ &sensor_dev_attr_rpm_psu1.dev_attr.attr,
+ &sensor_dev_attr_rpm_psu2.dev_attr.attr,
+
+ //switch temperature
+ &sensor_dev_attr_switch_tmp.dev_attr.attr,
+ &sensor_dev_attr_temp6_input.dev_attr.attr,
+ //diag flag
+ &sensor_dev_attr_diag.dev_attr.attr,
+
+ //version
+ &sensor_dev_attr_version.dev_attr.attr,
+
+ //fan led
+ &sensor_dev_attr_fan_led_grn1.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn2.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn3.dev_attr.attr,
+ &sensor_dev_attr_fan_led_grn4.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red1.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red2.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red3.dev_attr.attr,
+ &sensor_dev_attr_fan_led_red4.dev_attr.attr,
+
+ //fan GPI
+ &sensor_dev_attr_fan_gpi.dev_attr.attr,
+
+ //psu
+ &sensor_dev_attr_psu1_vin.dev_attr.attr,
+ &sensor_dev_attr_psu1_vout.dev_attr.attr,
+ &sensor_dev_attr_psu1_iin.dev_attr.attr,
+ &sensor_dev_attr_psu1_iout.dev_attr.attr,
+ &sensor_dev_attr_psu1_pin.dev_attr.attr,
+ &sensor_dev_attr_psu1_pout.dev_attr.attr,
+ &sensor_dev_attr_psu2_vin.dev_attr.attr,
+ &sensor_dev_attr_psu2_vout.dev_attr.attr,
+ &sensor_dev_attr_psu2_iin.dev_attr.attr,
+ &sensor_dev_attr_psu2_iout.dev_attr.attr,
+ &sensor_dev_attr_psu2_pin.dev_attr.attr,
+ &sensor_dev_attr_psu2_pout.dev_attr.attr,
+
+ &sensor_dev_attr_psu1_vendor.dev_attr.attr,
+ &sensor_dev_attr_psu1_model.dev_attr.attr,
+ &sensor_dev_attr_psu1_version.dev_attr.attr,
+ &sensor_dev_attr_psu1_date.dev_attr.attr,
+ &sensor_dev_attr_psu1_sn.dev_attr.attr,
+ &sensor_dev_attr_psu2_vendor.dev_attr.attr,
+ &sensor_dev_attr_psu2_model.dev_attr.attr,
+ &sensor_dev_attr_psu2_version.dev_attr.attr,
+ &sensor_dev_attr_psu2_date.dev_attr.attr,
+ &sensor_dev_attr_psu2_sn.dev_attr.attr,
+
+ &sensor_dev_attr_psu0.dev_attr.attr,
+ &sensor_dev_attr_psu1.dev_attr.attr,
+
+
+ //psu_psoc, new added on psoc 1.9
+ &sensor_dev_attr_psoc_psu1_vin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_vout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_iin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_iout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_pin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_pout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_iin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_iout.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_pin.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_pout.dev_attr.attr,
+
+ //add info
+ &sensor_dev_attr_psoc_psu1_vendor.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_model.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_version.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_date.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu1_sn.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_model.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_version.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_date.dev_attr.attr,
+ &sensor_dev_attr_psoc_psu2_sn.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group psoc_group = {
+ .attrs = psoc_attributes,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* device probe and removal */
+
+static int
+psoc_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct psoc_data *data;
+ int status;
+
+ printk("+%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct psoc_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+ data->diag = 0;
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &psoc_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;
+ }
+
+ 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, &psoc_group);
+exit_free:
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return status;
+}
+
+static int psoc_remove(struct i2c_client *client)
+{
+ struct psoc_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &psoc_group);
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return 0;
+}
+
+static const struct i2c_device_id psoc_ids[] = {
+ { "inv_psoc", 0, },
+ { /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, psoc_ids);
+
+static struct i2c_driver psoc_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "inv_psoc",
+ },
+ .probe = psoc_probe,
+ .remove = psoc_remove,
+ .id_table = psoc_ids,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* module glue */
+
+static int __init inv_psoc_init(void)
+{
+ return i2c_add_driver(&psoc_driver);
+}
+
+static void __exit inv_psoc_exit(void)
+{
+ i2c_del_driver(&psoc_driver);
+}
+
+MODULE_AUTHOR("eddie.lan ");
+MODULE_DESCRIPTION("inv psoc driver");
+MODULE_LICENSE("GPL");
+
+module_init(inv_psoc_init);
+module_exit(inv_psoc_exit);
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c
new file mode 100644
index 000000000000..7d3287a591c6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_pthread.c
@@ -0,0 +1,1312 @@
+/*
+ * 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.
+ */
+
+/*****************************
+ Magnolia platform
+******************************/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#define SHOW_ATTR_WARNING ("N/A")
+#define SHOW_ATTR_NOTPRINT ("Not Available")
+#define SHOW_ATTR_NOTSUPPORT ("Not Support")
+
+#define INV_HWMID_MAX (10)
+#define INV_HWMID_INIT (-1)
+
+/*access userspace data to kernel space*/
+#define ACC_R (0)
+#define ACC_W (1)
+
+#define TINY_BUF_SIZE (8)
+#define MAX_PATH_SIZE (64)
+#define MIN_ACC_SIZE (32)
+#define MAX_ACC_SIZE (256)
+
+/*
+ * LED definitions
+ */
+#define STATUS_LED_MODE_AUTO 0
+#define STATUS_LED_MODE_DIAG 1
+#define STATUS_LED_MODE_MANU 2
+
+#define STATUS_LED_GRN0 10 // 0 - 000: off
+#define STATUS_LED_GRN1 11 // 1 - 001: 0.5hz
+#define STATUS_LED_GRN2 12 // 2 - 010: 1 hz
+#define STATUS_LED_GRN3 13 // 3 - 011: 2 hz
+#define STATUS_LED_GRN7 17 // 7 - 111: on
+#define STATUS_LED_RED0 20 // 0 - 000: off
+#define STATUS_LED_RED1 21 // 1 - 001: 0.5hz
+#define STATUS_LED_RED2 22 // 2 - 010: 1 hz
+#define STATUS_LED_RED3 23 // 3 - 011: 2 hz
+#define STATUS_LED_RED7 27 // 7 - 111: on
+#define STATUS_LED_INVALID 0 // Invalid
+
+ssize_t status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2);
+ssize_t status_led_grn(const char *freq);
+ssize_t status_led_red(const char *freq);
+ssize_t status_led_diag_mode_enable(void);
+ssize_t status_led_diag_mode_disable(void);
+int status_led_check_color(void);
+int status_led_check_diag_mode(void);
+
+#if 1
+/* For timestamps in SYSFS_LOG */
+#define SYSFS_LOG printk
+#else
+//#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[SYSFS] %s/%d: " fmt, __func__, __LINE__, ##args)
+#define SYSFS_LOG(fmt, args...) printk(KERN_WARNING "[p_thread] " fmt, ##args)
+#endif
+
+#define INV_PTHREAD_KERNEL_MODULE (1)
+#define SWITCH_HEALTH_LED_CHANGE_VIA_GPIO (1)
+
+/* inventec_class *********************************/
+static struct kobject *status_kobj;
+static struct kset *status_kset;
+
+
+static struct mutex rw_lock;
+
+static int hwm_psoc = INV_HWMID_INIT;
+static int hwm_cpld = INV_HWMID_INIT;
+
+int get_hwm_psoc(void)
+{
+ return hwm_psoc;
+}
+
+int get_hwm_cpld(void)
+{
+ return hwm_cpld;
+}
+
+static ssize_t access_user_space(const char *name, int mode, char *buf, size_t len, loff_t offset)
+{
+ struct file *fp;
+ mm_segment_t fs;
+ loff_t pos = offset;
+ char *mark = NULL;
+ ssize_t vfs_ret = 0;
+
+ if (mode == ACC_R) {
+ fp = filp_open(name, O_RDONLY, S_IRUGO);
+ if (IS_ERR(fp))
+ return -ENODEV;
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ vfs_ret = vfs_read(fp, buf, len, &pos);
+
+ mark = strpbrk(buf, "\n");
+ if (mark)
+ *mark = '\0';
+
+ filp_close(fp, NULL);
+ set_fs(fs);
+ } else if (mode == ACC_W) {
+ fp = filp_open(name, O_WRONLY, S_IWUSR | S_IRUGO);
+ if (IS_ERR(fp))
+ return -ENODEV;
+
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ vfs_ret = vfs_write(fp, buf, len, &pos);
+ filp_close(fp, NULL);
+ set_fs(fs);
+ }
+
+ return vfs_ret;
+}
+
+int inventec_strtol(const char *sbufp, char **endp, unsigned int base)
+{
+ char *endptr;
+ int value = simple_strtol(sbufp, &endptr, base);
+ if (value == 0 && sbufp == endptr) {
+ *endp = NULL;
+ return value;
+ }
+ *endp = (char*)1;
+ return value;
+}
+
+int inventec_singlechar_to_int(const char c)
+{
+ if ((c >= '0') && (c <= '9')) {
+ return (c - '0');
+ }
+ else
+ if ((c >= 'a') && (c <= 'f')) {
+ return (c - 'a' + 10);
+ }
+ else
+ if ((c >= 'A') && (c <= 'F')) {
+ return (c - 'A' + 10);
+ }
+ return -1;
+}
+
+int inventec_store_input(char *inputp, int count)
+{
+ int i = 0;
+ while(inputp[i] != '\n' && inputp[i] != '\0' && i < count) {
+ i++;
+ }
+ inputp[i] = '\0';
+ return strlen(inputp);
+}
+
+#if 0
+/*
+ * Time stamps for kernel log on yocto
+ */
+#include
+
+void SYSFS_LOG(char *fmt, ...)
+{
+ char buf[80], ts[32];
+ va_list args;
+ int hlen;
+
+ inventec_tmstmp(&ts[0]);
+ hlen = sprintf(buf, "[SYSFS] %s ", ts); // Do not edit this line
+
+ va_start(args, fmt);
+ vsprintf(&buf[hlen-1], fmt, args);
+ va_end(args);
+ printk(KERN_WARNING "[p_thread] %s\n", buf);
+}
+#endif
+
+ssize_t
+inventec_show_attr(char *buf_p, const char *invdevp)
+{
+ int inv_len = MAX_ACC_SIZE; /* INV driver return max length */
+ char tmp_buf[MAX_ACC_SIZE];
+ char *str_negative = "-", *mark = NULL;
+
+ /* [Step2] Get data by uaccess */
+ memset(tmp_buf, 0, sizeof(tmp_buf));
+ mutex_lock(&rw_lock);
+ if (access_user_space(invdevp, ACC_R, tmp_buf, inv_len, 0) < 0) {
+ /* u_access fail */
+ mutex_unlock(&rw_lock);
+ return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING);
+ }
+ mutex_unlock(&rw_lock);
+
+ /* [Step3] Check return value
+ * - Ex: When transceiver not plugged
+ * => SWPS return error code "-202"
+ * => Pic8 need return "NA" (assume)
+ */
+ if (strcspn(tmp_buf, str_negative) == 0) {
+ /* error case: "-202" */
+ return sprintf(buf_p, "%s\n", SHOW_ATTR_WARNING);
+ }
+
+ /* OK case:*/
+ mark = strpbrk(tmp_buf, "\n");
+ if (mark) { *mark = '\0'; }
+
+ return sprintf(buf_p, "%s\n", tmp_buf);
+}
+
+ssize_t
+inventec_store_attr(const char *buf_p, size_t count, const char *invdevp)
+{
+ ssize_t ret = 0;
+
+ /* [Step2] Get data by uaccess */
+ mutex_lock(&rw_lock);
+ if ((ret = access_user_space(invdevp, ACC_W, (char*)buf_p, count, 0)) < 0) {
+ /* u_access fail */
+ mutex_unlock(&rw_lock);
+ return -EINVAL;
+ }
+ mutex_unlock(&rw_lock);
+
+ /* OK case:*/
+ return ret;
+}
+
+int sysfs_detect_hwmon_index(void)
+{
+ char hwmon_buf[MAX_ACC_SIZE];
+ char hwmon_path[MAX_PATH_SIZE];
+ int hwid = 0;
+
+ for (hwid = 0;
+ hwid < INV_HWMID_MAX && (hwm_psoc == INV_HWMID_INIT || hwm_cpld == INV_HWMID_INIT);
+ hwid++) {
+ memset(hwmon_buf, 0, sizeof(hwmon_buf));
+ sprintf(hwmon_path, "/sys/class/hwmon/hwmon%d/device/name", hwid);
+
+ inventec_show_attr(hwmon_buf, hwmon_path);
+ if (strncmp(hwmon_buf, "inv_psoc", 8) == 0) {
+ hwm_psoc = hwid;
+ }
+ else
+ if (strncmp(hwmon_buf, "inv_bmc", 7) == 0) {
+ hwm_psoc = hwid;
+ }
+ else
+ if (strncmp(hwmon_buf, "inv_cpld", 8) == 0) {
+ hwm_cpld = hwid;
+ }
+ }
+ if (hwid >= INV_HWMID_MAX) {
+ printk(KERN_ERR "[p_thread] detect hwmon index failed, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld);
+ return -1;
+ }
+ printk(KERN_INFO "[p_thread] detect hwmon index success, psoc = %d, cpld = %d\n", hwm_psoc, hwm_cpld);
+ return 0;
+}
+
+static int __init
+inventec_class_init(void)
+{
+ mutex_init(&rw_lock);
+
+#ifdef INV_PTHREAD_KERNEL_MODULE
+ if (sysfs_detect_hwmon_index() < 0) {
+ return -1;
+ }
+#endif
+
+ printk(KERN_INFO "[p_thread] [%s/%d] Module initial success.\n",__func__,__LINE__);
+
+ return 0;
+}
+
+static void __exit
+inventec_class_exit(void)
+{
+ printk(KERN_INFO "[p_thread] [%s/%d] Remove module.\n",__func__,__LINE__);
+}
+
+/* fan device *************************************/
+#define FAN_DEV_PATH_STATE "/sys/class/hwmon/hwmon%d/device/fan_gpi"
+#define FAN_DEV_PATH_FAN1_INPUT "/sys/class/hwmon/hwmon%d/device/fan1_input"
+#define FAN_DEV_PATH_FAN2_INPUT "/sys/class/hwmon/hwmon%d/device/fan2_input"
+#define FAN_DEV_PATH_FAN3_INPUT "/sys/class/hwmon/hwmon%d/device/fan3_input"
+#define FAN_DEV_PATH_FAN4_INPUT "/sys/class/hwmon/hwmon%d/device/fan4_input"
+#define FAN_DEV_PATH_FAN5_INPUT "/sys/class/hwmon/hwmon%d/device/fan5_input"
+#define FAN_DEV_PATH_FAN6_INPUT "/sys/class/hwmon/hwmon%d/device/fan6_input"
+#define FAN_DEV_PATH_FAN7_INPUT "/sys/class/hwmon/hwmon%d/device/fan7_input"
+#define FAN_DEV_PATH_FAN8_INPUT "/sys/class/hwmon/hwmon%d/device/fan8_input"
+
+static char fan_dev_path_state[MAX_PATH_SIZE];
+static char fan_dev_path_fan1_input[MAX_PATH_SIZE];
+static char fan_dev_path_fan2_input[MAX_PATH_SIZE];
+static char fan_dev_path_fan3_input[MAX_PATH_SIZE];
+static char fan_dev_path_fan4_input[MAX_PATH_SIZE];
+static char fan_dev_path_fan5_input[MAX_PATH_SIZE];
+static char fan_dev_path_fan6_input[MAX_PATH_SIZE];
+static char fan_dev_path_fan7_input[MAX_PATH_SIZE];
+static char fan_dev_path_fan8_input[MAX_PATH_SIZE];
+
+void sysfs_fan_path_init(void)
+{
+ sprintf(&fan_dev_path_state[0], FAN_DEV_PATH_STATE, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan1_input[0],FAN_DEV_PATH_FAN1_INPUT, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan2_input[0],FAN_DEV_PATH_FAN2_INPUT, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan3_input[0],FAN_DEV_PATH_FAN3_INPUT, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan4_input[0],FAN_DEV_PATH_FAN4_INPUT, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan5_input[0],FAN_DEV_PATH_FAN5_INPUT, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan6_input[0],FAN_DEV_PATH_FAN6_INPUT, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan7_input[0],FAN_DEV_PATH_FAN7_INPUT, get_hwm_psoc());
+ sprintf(&fan_dev_path_fan8_input[0],FAN_DEV_PATH_FAN8_INPUT, get_hwm_psoc());
+}
+
+#define FAN_STATE_NORMAL "normal"
+#define FAN_STATE_FAULTY "faulty"
+#define FAN_STATE_UNINSTALLED "uninstalled"
+#define FAN_STATE_UNKNOW "unknown state"
+#define FAN_STATE_INVALID "Invalid state value"
+#define FAN_STATE_READ_ERROR "state read error"
+
+#define FAN_LOG_UNINSTALLED "removed"
+#define FAN_LOG_NORMAL "inserted"
+
+//#define FAN_STATE_BIT_NORMAL 0
+#define FAN_STATE_BIT_FAULTY 0
+#define FAN_STATE_BIT_UNINSTALLED 1
+#define FAN_STATE_BIT_UNKNOW 2
+#define FAN_STATE_BIT_INVALID 3
+#define FAN_STATE_BIT_READ_ERROR 4
+
+static struct fans_tbl_s {
+ char *fan_name;
+ char *fan_front;
+ char *fan_rear;
+ unsigned int fan_state;
+} fans_tbl[] = {
+ {"fan1", fan_dev_path_fan1_input,
+ fan_dev_path_fan2_input, 0},
+ {"fan2", fan_dev_path_fan3_input,
+ fan_dev_path_fan4_input, 0},
+ {"fan3", fan_dev_path_fan5_input,
+ fan_dev_path_fan6_input, 0},
+ {"fan4", fan_dev_path_fan7_input,
+ fan_dev_path_fan8_input, 0},
+};
+#define FAN_TBL_TOTAL ( sizeof(fans_tbl)/ sizeof(const struct fans_tbl_s) )
+
+#define FAN_STATE_CHECK(i,b) (fans_tbl[i].fan_state & (1< 0)
+ {
+ printk(KERN_ERR "[p_thread] All fans failed.\n");
+ printk(KERN_ERR "[p_thread] System shutdown immediately in %d seconds.\n", cd_shutdown);
+ }
+ cd_shutdown -= 1;
+ }
+ return ret;
+}
+
+/* End of faninfo_device */
+
+static int __init
+fan_device_init(void)
+{
+#ifdef INV_PTHREAD_KERNEL_MODULE
+ sysfs_fan_path_init();
+#endif
+ return 0;
+}
+
+
+static void __exit
+fan_device_exit(void)
+{
+ printk(KERN_INFO "[p_thread] Remove fan module.\n");
+}
+
+/* psu device *************************************/
+static unsigned int psu_voltin = 0;
+#define PSU_VOLTIN_ACDC (70000)
+
+/*
+ * normal/unpower/uninstall/fault are PSU states output from driver level
+ * checkpsu/error are defined by sysfs
+ */
+#define PSU_STATE_VAL_NORMAL (0)
+#define PSU_STATE_VAL_UNPOWER (2)
+#define PSU_STATE_VAL_FAULT (4)
+#define PSU_STATE_VAL_UNINSTALL (7)
+#define PSU_STATE_VAL_CHECKPSU (8)
+#define PSU_STATE_VAL_ERROR (9)
+
+#define PSU_STATE_NORMAL ("0 : normal")
+#define PSU_STATE_UNPOWER ("2 : unpowered")
+#define PSU_STATE_FAULT ("4 : fault")
+#define PSU_STATE_UNINSTALL ("7 : not installed")
+#define PSU_STATE_CHECKPSU ("8 : check psu")
+#define PSU_STATE_ERROR ("9 : state error")
+
+#define PSU_STATE_LEN_NORMAL (strlen(PSU_STATE_NORMAL))
+#define PSU_STATE_LEN_UNPOWER (strlen(PSU_STATE_UNPOWER))
+#define PSU_STATE_LEN_FAULT (strlen(PSU_STATE_FAULT))
+#define PSU_STATE_LEN_UNINSTALL (strlen(PSU_STATE_UNINSTALL))
+#define PSU_STATE_LEN_CHECKPSU (strlen(PSU_STATE_CHECKPSU))
+
+typedef struct {
+ char *inv_dev_attrp;
+ char *inv_dev_pathp;
+} psu_dev_t;
+
+typedef struct {
+ const char *psu_name;
+ int psu_major;
+ dev_t psu_devt;
+ struct device *psu_dev_p;
+ psu_dev_t *psu_dev_namep;
+ int psu_dev_total;
+ char *psu_inv_pathp;
+ void *psu_tracking;
+ char *psu_currentin;
+ char *psu_currentout;
+ char *psu_powerin;
+ char *psu_powerout;
+ char *psu_voltin;
+ char *psu_voltout;
+} psu_dev_group_t;
+
+#define PSU_DEV_PATH_TEMPLATE "/sys/class/hwmon/hwmon%d/device/%s"
+
+static char psu_dev_path_state[MAX_PATH_SIZE];
+static char psu_dev_path_psu_voltin[MAX_PATH_SIZE];
+#if 0
+static char psu_dev_path_vendor[MAX_PATH_SIZE];
+static char psu_dev_path_version[MAX_PATH_SIZE];
+static char psu_dev_path_sn[MAX_PATH_SIZE];
+static char psu_dev_path_temperature[MAX_PATH_SIZE];
+static char psu_dev_path_fan_speed[MAX_PATH_SIZE];
+static char psu_dev_path_fan_pwm[MAX_PATH_SIZE];
+static char psu_dev_path_fan_faulty[MAX_PATH_SIZE];
+static char psu_dev_path_psu_currentin[MAX_PATH_SIZE];
+static char psu_dev_path_psu_currentout[MAX_PATH_SIZE];
+static char psu_dev_path_psu_powerin[MAX_PATH_SIZE];
+static char psu_dev_path_psu_powerout[MAX_PATH_SIZE];
+static char psu_dev_path_psu_voltout[MAX_PATH_SIZE];
+static char psu_dev_path_psu_pwm[MAX_PATH_SIZE];
+static char psu_dev_path_psu_rpm[MAX_PATH_SIZE];
+#endif
+
+void sysfs_psu_path_init(void)
+{
+ sprintf(&psu_dev_path_state[0], PSU_DEV_PATH_TEMPLATE, get_hwm_cpld(), "\%s" );
+ sprintf(&psu_dev_path_psu_voltin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+#if 0
+ sprintf(&psu_dev_path_vendor[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_version[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_sn[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_temperature[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_fan_speed[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_fan_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_fan_faulty[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_psu_currentin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_psu_currentout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_psu_powerin[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_psu_powerout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_psu_voltout[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_psu_pwm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+ sprintf(&psu_dev_path_psu_rpm[0], PSU_DEV_PATH_TEMPLATE, get_hwm_psoc(), "\%s" );
+#endif
+}
+
+static psu_dev_t psu_dev_name[] = {
+ { "state", psu_dev_path_state }, // Using cpld
+ { "psu_voltin", psu_dev_path_psu_voltin },
+#if 0
+ { "vendor", psu_dev_path_vendor },
+ { "version", psu_dev_path_version },
+ { "sn", psu_dev_path_sn },
+ { "temperature", psu_dev_path_temperature },
+ { "fan_speed", psu_dev_path_fan_speed },
+ { "fan_pwm", psu_dev_path_fan_pwm },
+ { "fan_faulty", psu_dev_path_fan_faulty },
+ { "psu_currentin", psu_dev_path_psu_currentin },
+ { "psu_currentout", psu_dev_path_psu_currentout },
+ { "psu_powerin", psu_dev_path_psu_powerin },
+ { "psu_powerout", psu_dev_path_psu_powerout },
+ { "psu_voltout", psu_dev_path_psu_voltout },
+ { "psu_pwm", psu_dev_path_psu_pwm },
+ { "psu_rpm", psu_dev_path_psu_rpm },
+#endif
+};
+#define PSU_DEV_NAME_TOTAL ( sizeof(psu_dev_name) / sizeof(const psu_dev_t) )
+
+static psu_dev_group_t psu_dev_group[] = {
+ {
+ .psu_name = "psu1",
+ .psu_dev_namep = &psu_dev_name[0],
+ .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t),
+ },
+ {
+ .psu_name = "psu2",
+ .psu_dev_namep = &psu_dev_name[0],
+ .psu_dev_total = sizeof(psu_dev_name) / sizeof(const psu_dev_t),
+ },
+};
+#define PSU_DEV_GROUP_TOTAL ( sizeof(psu_dev_group)/ sizeof(const psu_dev_group_t) )
+
+static char psu_state[4][MIN_ACC_SIZE];
+
+static struct psu_wire_tbl_s {
+ char *psu_attr;
+ char *psu_name;
+ char *psu_wire;
+ char *psu_state;
+} psu_wire_tbl[] = {
+ { "state", "psu1", "psu0", psu_state[0] }, // Using cpld
+ { "state", "psu2", "psu1", psu_state[1] },
+ { "psu_voltin", "psu1", "psoc_psu1_vin", psu_state[2] },
+ { "psu_voltin", "psu2", "psoc_psu2_vin", psu_state[3] },
+};
+#define PSU_WIRE_TBL_TOTAL ( sizeof(psu_wire_tbl)/ sizeof(const struct psu_wire_tbl_s) )
+
+static char *
+psu_attr_get_wirep(const char *psu_attrp, const char *psu_namep, char **psu_statepp)
+{
+ int i;
+
+ for (i = 0; i < PSU_WIRE_TBL_TOTAL; i++) {
+ if (strncmp(psu_wire_tbl[i].psu_attr, psu_attrp, strlen(psu_attrp)) == 0 &&
+ strncmp(psu_wire_tbl[i].psu_name, psu_namep, strlen(psu_namep)) == 0) {
+ if (psu_statepp) {
+ *psu_statepp = psu_wire_tbl[i].psu_state;
+ }
+ return psu_wire_tbl[i].psu_wire;
+ }
+ }
+ return NULL;
+}
+
+int psu_check_state_normal(char *statep)
+{
+ if (strstr(statep, "normal")) {
+ return 1;
+ }
+ return 0;
+}
+
+#define PSU_ATTR_VOLTIN ("psu_voltin")
+#define PSU_ATTR_VOLTIN_LEN (10)
+
+/* Get PSU voltin for determon AC(110v) or DC(48v) */
+void psu_get_voltin(void)
+{
+ char acc_path[MAX_PATH_SIZE], volt[MIN_ACC_SIZE];
+ psu_dev_t *devnamep;
+ unsigned int voltin;
+ char *invwirep;
+ int i, j;
+
+ for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) {
+ //psu_dev_group[i].psu_name;
+ devnamep = psu_dev_group[i].psu_dev_namep;
+ for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) {
+ if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_VOLTIN, PSU_ATTR_VOLTIN_LEN) == 0) {
+ invwirep = psu_attr_get_wirep(PSU_ATTR_VOLTIN, psu_dev_group[i].psu_name, NULL);
+ if (invwirep == NULL) {
+ printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name);
+ continue;
+ }
+ sprintf(acc_path, devnamep->inv_dev_pathp, invwirep);
+ //printk(KERN_DEBUG "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path);
+ if (inventec_show_attr(volt, acc_path) <= 0) {
+ printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path);
+ continue;
+ }
+ else {
+ voltin = simple_strtol(&volt[0], NULL, 10);
+ printk(KERN_DEBUG "[p_thread] Read %s %s = %u\n",acc_path,volt,voltin);
+ if (voltin > psu_voltin) {
+ psu_voltin = voltin;
+ }
+ }
+ }
+ }
+ }
+
+ SYSFS_LOG("[p_thread] PSU voltin = %u\n", psu_voltin);
+}
+
+#define PSU_ATTR_STATE ("state")
+#define PSU_ATTR_STATE_LEN (5)
+
+/* psus_control() by inv_thread */
+int psus_control(int log_only)
+{
+ char acc_path[MAX_PATH_SIZE], state[MIN_ACC_SIZE];
+ psu_dev_t *devnamep = NULL;
+ char *invwirep = NULL;
+ char *psu_statep = NULL;
+ int i, j, flag = 0;
+
+ for (i = 0; i < PSU_DEV_GROUP_TOTAL; i++) {
+ devnamep = psu_dev_group[i].psu_dev_namep;
+ for (j = 0; j < psu_dev_group[i].psu_dev_total; j++, devnamep++) {
+ if (strncmp(devnamep->inv_dev_attrp, PSU_ATTR_STATE, PSU_ATTR_STATE_LEN) == 0) {
+ invwirep = psu_attr_get_wirep(PSU_ATTR_STATE, psu_dev_group[i].psu_name, &psu_statep);
+ if (invwirep == NULL) {
+ printk(KERN_DEBUG "[p_thread] Invalid psuname: %s\n", psu_dev_group[i].psu_name);
+ continue;
+ }
+ sprintf(acc_path, devnamep->inv_dev_pathp, invwirep);
+ //printk(KERN_INFO "[p_thread] RYU: %s/%d: acc_path = %s\n",__func__,__LINE__,acc_path);
+ if (inventec_show_attr(state, acc_path) <= 0) {
+ printk(KERN_DEBUG "[p_thread] Read %s failed\n", acc_path);
+ if (strncmp(psu_statep, PSU_STATE_ERROR, strlen(PSU_STATE_ERROR)) != 0) {
+ strcpy(psu_statep, PSU_STATE_ERROR);
+ SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_ERROR);
+ }
+ flag = 1;
+ }
+ else
+ if (strstr(state, "normal")) {
+ //printk(KERN_INFO "[p_thread] %s: %s\n", psu_dev_group[i].psu_name, state);
+ if (strncmp(psu_statep, state, strlen(state)) != 0) {
+ strcpy(psu_statep, state);
+ SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state);
+ }
+ }
+ else
+ if (psu_voltin > PSU_VOLTIN_ACDC) { /* AC PSUS */
+ //printk(KERN_INFO "[p_thread] RYU: %s: %s\n", psu_dev_group[i].psu_name, state);
+ if (strncmp(psu_statep, state, strlen(state)) != 0) {
+ strcpy(psu_statep, state);
+ SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,state);
+ }
+ flag = 1;
+ }
+ else { /* DC PSUS */
+ if (strncmp(psu_statep, PSU_STATE_CHECKPSU, PSU_STATE_LEN_CHECKPSU) != 0) {
+ strcpy(psu_statep, PSU_STATE_CHECKPSU);
+ SYSFS_LOG("[p_thread] %s: %s\n",psu_dev_group[i].psu_name,PSU_STATE_CHECKPSU);
+ }
+ flag = 1;
+ }
+ }
+ }
+ }
+
+ if (log_only) {
+ return 0;
+ }
+
+ //SYSFS_LOG("[p_thread] RYU: %s: flag = %d\n",psu_wire_tbl[i].psu_name,flag);
+ if (flag == 1) {
+ status_led_grn("3");
+ return 1;
+ }
+ return 0;
+}
+
+/* End of psuinfo_device */
+
+static int __init
+psu_device_init(void)
+{
+#ifdef INV_PTHREAD_KERNEL_MODULE
+ sysfs_psu_path_init();
+#endif
+ return 0;
+}
+
+
+static void __exit
+psu_device_exit(void)
+{
+ printk(KERN_INFO "[p_thread] Remove psu module.\n");
+}
+
+/* led device *************************************/
+#define STATUS_LED_GRN_PATH "/sys/class/hwmon/hwmon%d/device/grn_led"
+#define STATUS_LED_RED_PATH "/sys/class/hwmon/hwmon%d/device/red_led"
+
+#define FAN_LED_GRN1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn1"
+#define FAN_LED_GRN2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn2"
+#define FAN_LED_GRN3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn3"
+#define FAN_LED_GRN4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_grn4"
+#define FAN_LED_RED1_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red1"
+#define FAN_LED_RED2_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red2"
+#define FAN_LED_RED3_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red3"
+#define FAN_LED_RED4_PATH "/sys/class/hwmon/hwmon%d/device/fan_led_red4"
+
+#define HWMON_DEVICE_DIAG_PATH "/sys/class/hwmon/hwmon%d/device/diag"
+#define HWMON_DEVICE_CTRL_PATH "/sys/class/hwmon/hwmon%d/device/ctl"
+
+static char status_led_grn_path[MAX_PATH_SIZE];
+static char status_led_red_path[MAX_PATH_SIZE];
+static char fan_led_grn1_path[MAX_PATH_SIZE];
+static char fan_led_grn2_path[MAX_PATH_SIZE];
+static char fan_led_grn3_path[MAX_PATH_SIZE];
+static char fan_led_grn4_path[MAX_PATH_SIZE];
+static char fan_led_red1_path[MAX_PATH_SIZE];
+static char fan_led_red2_path[MAX_PATH_SIZE];
+static char fan_led_red3_path[MAX_PATH_SIZE];
+static char fan_led_red4_path[MAX_PATH_SIZE];
+static char hwmon_device_diag_path[MAX_PATH_SIZE];
+static char hwmon_device_ctrl_path[MAX_PATH_SIZE];
+
+void sysfs_led_path_init(void)
+{
+ sprintf(&status_led_grn_path[0], STATUS_LED_GRN_PATH, get_hwm_cpld());
+ sprintf(&status_led_red_path[0], STATUS_LED_RED_PATH, get_hwm_cpld());
+ sprintf(&fan_led_grn1_path[0], FAN_LED_GRN1_PATH, get_hwm_psoc());
+ sprintf(&fan_led_grn2_path[0], FAN_LED_GRN2_PATH, get_hwm_psoc());
+ sprintf(&fan_led_grn3_path[0], FAN_LED_GRN3_PATH, get_hwm_psoc());
+ sprintf(&fan_led_grn4_path[0], FAN_LED_GRN4_PATH, get_hwm_psoc());
+ sprintf(&fan_led_red1_path[0], FAN_LED_RED1_PATH, get_hwm_psoc());
+ sprintf(&fan_led_red2_path[0], FAN_LED_RED2_PATH, get_hwm_psoc());
+ sprintf(&fan_led_red3_path[0], FAN_LED_RED3_PATH, get_hwm_psoc());
+ sprintf(&fan_led_red4_path[0], FAN_LED_RED4_PATH, get_hwm_psoc());
+ sprintf(&hwmon_device_diag_path[0], HWMON_DEVICE_DIAG_PATH, get_hwm_psoc());
+ sprintf(&hwmon_device_ctrl_path[0], HWMON_DEVICE_CTRL_PATH, get_hwm_cpld());
+}
+
+/* return 0/off 1/green 2/red */
+int
+status_led_check_color(void)
+{
+ char tmpbuf[MIN_ACC_SIZE];
+ int ret = STATUS_LED_INVALID;
+
+ if (inventec_show_attr(&tmpbuf[0], status_led_grn_path) > 0) {
+ if (tmpbuf[0] == '0') {
+ ret = STATUS_LED_GRN0;
+ }
+ if (tmpbuf[0] == '1') {
+ ret = STATUS_LED_GRN1;
+ }
+ if (tmpbuf[0] == '2') {
+ ret = STATUS_LED_GRN2;
+ }
+ if (tmpbuf[0] == '3') {
+ ret = STATUS_LED_GRN3;
+ }
+ if (tmpbuf[0] == '7') {
+ ret = STATUS_LED_GRN7;
+ }
+ return ret;
+ }
+
+ if (inventec_show_attr(&tmpbuf[0], status_led_red_path) > 0) {
+ if (tmpbuf[0] == '0') {
+ ret = STATUS_LED_RED0;
+ }
+ if (tmpbuf[0] == '1') {
+ ret = STATUS_LED_RED1;
+ }
+ if (tmpbuf[0] == '2') {
+ ret = STATUS_LED_RED2;
+ }
+ if (tmpbuf[0] == '3') {
+ ret = STATUS_LED_RED3;
+ }
+ if (tmpbuf[0] == '7') {
+ ret = STATUS_LED_RED7;
+ }
+ return ret;
+ }
+ return ret;
+}
+
+/*
+ * Store attr Section
+ */
+static DEFINE_MUTEX(diag_mutex);
+
+ssize_t status_led_diag_mode_enable(void)
+{
+ char tmp[MIN_ACC_SIZE];
+ ssize_t ret;
+
+ ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ if (tmp[0] == '0') {
+ mutex_lock(&diag_mutex);
+ ret = inventec_store_attr("1", 1, hwmon_device_diag_path);
+ if (ret < 0) {
+ mutex_unlock(&diag_mutex);
+ return ret;
+ }
+
+ ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path);
+ if (ret < 0) {
+ mutex_unlock(&diag_mutex);
+ return ret;
+ }
+ mutex_unlock(&diag_mutex);
+ }
+
+ return ret;
+}
+
+ssize_t status_led_diag_mode_disable(void)
+{
+ char tmp[MIN_ACC_SIZE];
+ ssize_t ret;
+
+ ret = inventec_show_attr(&tmp[0], hwmon_device_diag_path);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ if (tmp[0] == '1') {
+ mutex_lock(&diag_mutex);
+ ret = inventec_store_attr("0", 1, hwmon_device_diag_path);
+ if (ret < 0) {
+ mutex_unlock(&diag_mutex);
+ return 1;
+ }
+
+ ret = inventec_store_attr("1", 1, hwmon_device_ctrl_path);
+ if (ret < 0) {
+ mutex_unlock(&diag_mutex);
+ return 1;
+ }
+ mutex_unlock(&diag_mutex);
+ }
+ return 1;
+}
+
+ssize_t
+status_led_change(const char *path1, const char *tmp1, const char *path2, const char *tmp2)
+{
+ ssize_t ret;
+
+ ret = inventec_store_attr(tmp1, strlen(tmp1), path1);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = inventec_store_attr(tmp2, strlen(tmp2), path2);
+ if (ret < 0) {
+ return ret;
+ }
+ if ((ret = status_led_diag_mode_enable()) <= 0) {
+ return ret;
+ }
+ ssleep(1);
+ if ((ret = status_led_diag_mode_disable()) <= 0) {
+ return ret;
+ }
+ return ret;
+}
+
+ssize_t
+status_led_red(const char *freq)
+{
+ ssize_t ret;
+
+ ret = inventec_store_attr("0", 1, &status_led_grn_path[0]);
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = inventec_store_attr(freq, strlen(freq), &status_led_red_path[0]);
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ if ((ret = status_led_diag_mode_enable()) <= 0) {
+ return ret;
+ }
+ ssleep(1);
+ if ((ret = status_led_diag_mode_disable()) <= 0) {
+ return ret;
+ }
+ return ret;
+}
+
+ssize_t
+status_led_grn(const char *freq)
+{
+ ssize_t ret;
+
+ ret = inventec_store_attr("0", 1, &status_led_red_path[0]);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = inventec_store_attr(freq, strlen(freq), &status_led_grn_path[0]);
+ if (ret < 0) {
+ return ret;
+ }
+ if ((ret = status_led_diag_mode_enable()) <= 0) {
+ return ret;
+ }
+ ssleep(1);
+ if ((ret = status_led_diag_mode_disable()) <= 0) {
+ return ret;
+ }
+ return ret;
+}
+
+static int status_led_diag_mode = STATUS_LED_MODE_AUTO;
+
+int status_led_check_diag_mode(void)
+{
+ return status_led_diag_mode;
+}
+
+/* End of ledinfo_device */
+
+static int __init
+led_device_init(void)
+{
+#ifdef INV_PTHREAD_KERNEL_MODULE
+ sysfs_led_path_init();
+#endif
+ return 0;
+}
+
+
+static void __exit
+led_device_exit(void)
+{
+ printk(KERN_INFO "[p_thread] Remove led module.\n");
+}
+
+/* sensor device **********************************/
+#define SENSOR_DEV_PATH_SWITCH_TEMP "/sys/class/hwmon/hwmon%d/device/switch_tmp"
+
+static char sensor_dev_path_switch_temp[MAX_PATH_SIZE];
+
+void sysfs_sensor_path_init(void)
+{
+ sprintf(&sensor_dev_path_switch_temp[0], SENSOR_DEV_PATH_SWITCH_TEMP, get_hwm_psoc());
+}
+
+void switch_temp_update(void)
+{
+ char buf[MIN_ACC_SIZE];
+ ssize_t count = inventec_show_attr(&buf[0], "proc/switch/temp");
+ if (count > 0) {
+ //printk(KERN_ERR "[p_thread] [STEMP] Switch temperature is out of range: %d\n", stemp);
+ inventec_store_attr(&buf[0], count, sensor_dev_path_switch_temp);
+ }
+}
+
+/**************************************************/
+/* From system_device */
+static int inv_pthread_control = 1;
+
+int thread_control(void)
+{
+ return inv_pthread_control;
+}
+
+void thread_control_set(int val)
+{
+ inv_pthread_control = val;
+}
+/* End system_device */
+
+#define THREAD_SLEEP_MINS (3)
+#define THREAD_DELAY_MINS (THREAD_SLEEP_MINS + THREAD_SLEEP_MINS + 1)
+
+extern void psu_get_voltin(void);
+
+static struct task_struct *thread_st;
+static int thread_data;
+
+#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO
+void led_set_gpio_to_change_status_led(void)
+{
+ ssize_t ret = inventec_store_attr("253", 3, "/sys/class/gpio/export");
+ if (ret < 0) {
+ SYSFS_LOG("[p_thread] Write 253 to /sys/class/gpio/export failed\n");
+ return;
+ }
+
+ printk("[p_thread] Write 253 to /sys/class/gpio/export\n");
+
+ ret = inventec_store_attr("out", 3, "/sys/class/gpio/gpio253/direction");
+ if (ret < 0) {
+ SYSFS_LOG("[p_thread] Write low to /sys/class/gpio/gpio253/direction failed\n");
+ return;
+ }
+
+ //pull high and then low
+ ret = inventec_store_attr("1", 1, "sys/class/gpio/gpio253/value");
+ if (ret < 0) {
+ SYSFS_LOG("[p_thread] Write 1 to sys/class/gpio/gpio253/value failed\n");
+ }
+
+ //pull low
+ ret = inventec_store_attr("0", 1, "sys/class/gpio/gpio253/value");
+ if (ret < 0) {
+ SYSFS_LOG("[p_thread] Write 0 to sys/class/gpio/gpio253/value failed\n");
+ }
+
+ SYSFS_LOG("[p_thread] Set gpio to support status led change successfully\n");
+}
+#endif
+
+// Function executed by kernel thread
+static int thread_fn(void *unused)
+{
+ /* Delay for guarantee HW ready */
+ ssleep(THREAD_DELAY_MINS);
+
+#ifndef INV_PTHREAD_KERNEL_MODULE
+ sysfs_led_path_init();
+ sysfs_fan_path_init();
+ sysfs_psu_path_init();
+#endif
+ //sysfs_sensor_path_init();
+
+ /* Default status init */
+ status_led_grn("7");
+
+ psu_get_voltin();
+
+#ifdef SWITCH_HEALTH_LED_CHANGE_VIA_GPIO
+ led_set_gpio_to_change_status_led();
+#endif
+
+ while (1)
+ {
+ ssleep(THREAD_SLEEP_MINS);
+
+ if (thread_control() == 0) {
+ printk(KERN_INFO "[p_thread] %s/%d: Thread Stop by inv_pthread control\n",__func__,__LINE__);
+ break;
+ }
+
+ if (status_led_check_diag_mode() == STATUS_LED_MODE_MANU) {
+ /* status led in change color/freq mode, higher priority. Ignore fans sttaus */
+ continue;
+ }
+
+ //switch_temp_update();
+
+ if (fans_control() > 0) {
+ psus_control(1);
+ continue;
+ }
+ else
+ if (psus_control(0) > 0) {
+ continue;
+ }
+
+ if (status_led_check_color() != STATUS_LED_GRN7) { /* status led red, change it to green */
+ status_led_grn("7");
+ }
+ }
+
+#ifndef INV_PTHREAD_KERNEL_MODULE
+err_inv_pthread_fn_1:
+#endif
+ do_exit(0);
+ printk(KERN_INFO "[p_thread] %s/%d: Thread Stopped\n",__func__,__LINE__);
+ return 0;
+}
+
+
+static ssize_t s_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+ int fan_absence;
+ size_t count;
+
+ fan_absence = fans_control();
+ count += sprintf(&buf[count], "%d\n", fan_absence);
+ return count;
+}
+
+static ssize_t s_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)
+{
+ return count;
+}
+
+static struct attribute status_att = {
+ .name = "fan_absence",
+ .mode = 0777,
+};
+
+static const struct sysfs_ops status_ops = {
+ .show = s_show,
+ .store = s_store,
+};
+
+static struct kobj_type status_ktype = {
+ .sysfs_ops = &status_ops,
+};
+
+
+static int __init inv_pthread_init(void)
+{
+ int retval;
+
+ status_kobj = kzalloc(sizeof(*status_kobj), GFP_KERNEL);
+ if(!status_kobj)
+ return PTR_ERR(status_kobj);
+
+ status_kset = kset_create_and_add("platform_status", NULL, kernel_kobj);
+ if(!status_kset)
+ return -1;
+
+ status_kobj->kset = status_kset;
+
+ retval = kobject_init_and_add(status_kobj, &status_ktype, NULL, "fan");
+ if(retval)
+ return retval;
+
+ retval = sysfs_create_file(status_kobj, &status_att);
+
+
+ inventec_class_init();
+ fan_device_init();
+ psu_device_init();
+ led_device_init();
+
+ thread_control_set(1);
+
+ printk(KERN_INFO "[p_thread] %s/%d: Creating Thread\n",__func__,__LINE__);
+ //Create the kernel thread with name 'inv_pthread'
+ thread_st = kthread_run(thread_fn, (void*)&thread_data, "inv_pthread");
+ if (thread_st)
+ printk(KERN_INFO "[p_thread] inv_pthread Created successfully\n");
+ else
+ printk(KERN_ERR "[p_thread] inv_pthread creation failed\n");
+
+ return retval;
+}
+
+static void __exit inv_pthread_exit(void)
+{
+ thread_control_set(0);
+ /* Delay for guarantee thread exit */
+ ssleep(THREAD_DELAY_MINS);
+
+ fan_device_exit();
+ psu_device_exit();
+ led_device_exit();
+ inventec_class_exit();
+
+ sysfs_remove_file(status_kobj, &status_att);
+ kset_unregister(status_kset);
+ kobject_del(status_kobj);
+
+ printk(KERN_INFO "[p_thread] inv_pthread cleaning Up\n");
+}
+
+module_init(inv_pthread_init);
+module_exit(inv_pthread_exit);
+
+MODULE_AUTHOR("Robert ");
+MODULE_DESCRIPTION("Inventec Platform Management Thread");
+MODULE_VERSION("version 1.0");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c
new file mode 100644
index 000000000000..eff030df0a8a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.c
@@ -0,0 +1,3027 @@
+/*
+ * 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#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_currauto_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 :polling\n", __func__);
+ flag_i2c_reset = 1;
+ return count;
+ }
+ /* Direct mode */
+ SWPS_INFO("%s: reset I2C go. :direct\n", __func__);
+ if (reset_i2c_topology() < 0) {
+ SWPS_ERR("%s: reset fail!\n", __func__);
+ return -EIO;
+ }
+ SWPS_INFO("%s: reset I2C ok. :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_currstate = 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! :%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! :%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_curri2c_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; iname, 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:
+ platform_p->id = PLATFORM_SETTINGS;
+ for (i=0; iname, (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, :%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 :%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
+ 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 :%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:%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 :%d\n",
+ __func__, dev_name, retval);
+ return -2;
+ }
+ SWPS_DEBUG("%s: %s single error :%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:%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:
+ 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:
+ 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:
+ 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 :%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! :%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 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 :%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: :%d :%d :%d :%d :%d :%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 :%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 :%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/d6254qs/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.h
new file mode 100644
index 000000000000..8e1451d6149a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/inv_swps.h
@@ -0,0 +1,1033 @@
+/*
+ * 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 "
+#define SWP_DESC "Inventec port and transceiver driver"
+#define SWP_VERSION "4.2.7"
+#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)
+/* Current running platfrom */
+#define PLATFORM_SETTINGS PLATFORM_TYPE_MAGNOLIA
+
+/* 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)
+#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" },
+};
+
+
+/* ==========================================
+ * 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
+
+
+#endif /* INV_SWPS_H */
+
+
+
+
+
+
+
+
+
diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c
new file mode 100644
index 000000000000..9f1bbd0e4f2f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.c
@@ -0,0 +1,1885 @@
+/*
+ * 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
+#include
+#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) */
+};
+
+
+/* ========== 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! :%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_idread_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! :%d \n", self->ioexp_id, buf);
+ SWPS_INFO("Dump: :%d :0x%02x :%d, :%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_idioexp_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. :%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! :%d :%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! :%d :%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! :%d :%d :%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! :%d :%d :%s :%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! :%d \n",
+ __func__, chip_id);
+ return -1;
+ }
+ /* Setup default value */
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+ 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! :%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! :%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 :%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 :%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 :%d\n",
+ __func__, result_val);
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ default:
+ break;
+ }
+ SWPS_ERR("%s: Exception occurs :%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. :%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; iupdate_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 :%d\n",
+ __func__, self->ioexp_id);
+ break;
+ }
+ SWPS_DEBUG("IOEXP-%d: unstable :%d\n",
+ self->ioexp_id, result_val);
+ }
+ SWPS_INFO("IOEXP-%d: NORMAL -> ABNORMAL :%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 :%d\n",
+ self->ioexp_id, result_val);
+ self->state = STATE_IOEXP_NORMAL;
+ return 0;
+
+ default:
+ break;
+ }
+ SWPS_ERR("IOEXP-%d: Exception occurs :%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 :%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;
+ 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:
+ 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:
+ 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:
+ 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:
+ 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 :%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! :%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! :%d \n",chip_id);
+ return -1;
+ }
+ for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){
+
+ 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! :%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! :%d :%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! :%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. :%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/d6254qs/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h
new file mode 100644
index 000000000000..82fef3f7febc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/io_expander.h
@@ -0,0 +1,183 @@
+/*
+ * 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
+
+
+/* IOEXP type define (SFP series) */
+#define IOEXP_TYPE_MAGINOLIA_NAB (10101)
+#define IOEXP_TYPE_MAGINOLIA_4AB (10102)
+#define IOEXP_TYPE_CYPRESS_NABC (10103)
+
+/* 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)
+
+/* 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/d6254qs/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.c
new file mode 100644
index 000000000000..e7f3cf70fa68
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-inventec/d6254qs/modules/transceiver.c
@@ -0,0 +1,8388 @@
+/*
+ * 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
+#include
+#include
+#include
+#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: :0x%02x :%d :%d :%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 :%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; ii2c_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 :%s :%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; ii2c_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 :%s :%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; ii2c_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 :%s :%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 :%s :%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; ii2c_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 :%s :%d :%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 :%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 :%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 :%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; ilane_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; ii2c_client_p, self->extphy_offset);
+ if (ret >=0) {
+ goto ok_sfp_get_1g_rj45_extphy_reg;
+ }
+ msleep(delay);
+ }
+ SWPS_INFO("%s: retry:%d fail :%s :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 :%d :%s\n :%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 :%d :%s\n :%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 :%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; itx_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 :%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 :%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; irx_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 :%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 :%s :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 :%d :%s\n :%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 :%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 :%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! :%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 :%d :%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 :%s :%d\n :%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
+ */
+ 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 :%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; itx_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 :%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
+ */
+ 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 :%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; irx_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 :%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
+ */
+ 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 :%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; irx_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 :%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 " |- :%s\n", type_name);
+ printk(KERN_INFO " |- :%s\n", self->vendor_name);
+ printk(KERN_INFO " |- :%s\n", self->vendor_pn);
+ printk(KERN_INFO " |- :%s\n", self->vendor_rev);
+ printk(KERN_INFO " |- :%s\n", self->vendor_sn);
+ printk(KERN_INFO " |-