diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/hwsku.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/hwsku.json
new file mode 100644
index 000000000000..0992d683af0b
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/hwsku.json
@@ -0,0 +1,100 @@
+{
+ "interfaces": {
+ "Ethernet1": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet2": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet3": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet4": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet5": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet6": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet7": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet8": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet9": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet10": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet11": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet12": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet13": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet14": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet15": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet16": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet17": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet18": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet19": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet20": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet21": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet22": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet23": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet24": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet25": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet33": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet41": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet49": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet57": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet65": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet73": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet81": {
+ "default_brkout_mode": "1x400G"
+ }
+ }
+}
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/port_config.ini b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/port_config.ini
new file mode 100644
index 000000000000..28f3f3a348ac
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/port_config.ini
@@ -0,0 +1,33 @@
+# name lanes alias index speed
+Ethernet1 25,26,27,28 twoHundredGigE0/1 0 200000
+Ethernet2 29,30,31,32 twoHundredGigE0/2 1 200000
+Ethernet3 41,42,43,44 twoHundredGigE0/3 2 200000
+Ethernet4 45,46,47,48 twoHundredGigE0/4 3 200000
+Ethernet5 49,50,51,52 twoHundredGigE0/5 4 200000
+Ethernet6 53,54,55,56 twoHundredGigE0/6 5 200000
+Ethernet7 57,58,59,60 twoHundredGigE0/7 6 200000
+Ethernet8 61,62,63,64 twoHundredGigE0/8 7 200000
+Ethernet9 9,10,11,12 twoHundredGigE0/9 8 200000
+Ethernet10 13,14,15,16 twoHundredGigE0/10 9 200000
+Ethernet11 17,18,19,20 twoHundredGigE0/11 10 200000
+Ethernet12 21,22,23,24 twoHundredGigE0/12 11 200000
+Ethernet13 81,82,83,84 twoHundredGigE0/13 12 200000
+Ethernet14 85,86,87,88 twoHundredGigE0/14 13 200000
+Ethernet15 89,90,91,92 twoHundredGigE0/15 14 200000
+Ethernet16 93,94,95,96 twoHundredGigE0/16 15 200000
+Ethernet17 97,98,99,100 twoHundredGigE0/17 16 200000
+Ethernet18 101,102,103,104 twoHundredGigE0/18 17 200000
+Ethernet19 137,138,139,140 twoHundredGigE0/19 18 200000
+Ethernet20 141,142,143,144 twoHundredGigE0/20 19 200000
+Ethernet21 145,146,147,148 twoHundredGigE0/21 20 200000
+Ethernet22 149,150,151,152 twoHundredGigE0/22 21 200000
+Ethernet23 153,154,155,156 twoHundredGigE0/23 22 200000
+Ethernet24 157,158,159,160 twoHundredGigE0/24 23 200000
+Ethernet25 1,2,3,4,5,6,7,8 fourHundredGigE0/1 24 400000
+Ethernet33 33,34,35,36,37,38,39,40 fourHundredGigE0/2 25 400000
+Ethernet41 65,66,67,68,69,70,71,72 fourHundredGigE0/3 26 400000
+Ethernet49 73,74,75,76,77,78,79,80 fourHundredGigE0/4 27 400000
+Ethernet57 105,106,107,108,109,110,111,112 fourHundredGigE0/5 28 400000
+Ethernet65 113,114,115,116,117,118,119,120 fourHundredGigE0/6 29 400000
+Ethernet73 121,122,123,124,125,126,127,128 fourHundredGigE0/7 30 400000
+Ethernet81 129,130,131,132,133,134,135,136 fourHundredGigE0/8 31 400000
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/sai.profile b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/sai.profile
new file mode 100644
index 000000000000..4b3cbf7154af
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td4-m2-w6520-24dc8qc-24x200G+8x400G.yml
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/td4-m2-w6520-24dc8qc-24x200G+8x400G-copper.yml b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/td4-m2-w6520-24dc8qc-24x200G+8x400G-copper.yml
new file mode 100644
index 000000000000..0f50428f47bd
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/td4-m2-w6520-24dc8qc-24x200G+8x400G-copper.yml
@@ -0,0 +1,4049 @@
+---
+bcm_device:
+ 0:
+ global:
+ bcm_tunnel_term_compatible_mode: 1
+ vlan_flooding_l2mc_num_reserved: 2048
+ l3_alpm_template: 2
+ l3_alpm2_bnk_threshold: 100
+ uft_mode: 1
+ l3_enable: 1
+ l2_hitbit_enable: 0
+ pktio_mode: 1
+ warmboot_knet_shutdown_mode: 1
+ sai_optimized_mmu: 1
+...
+
+---
+bcm_device:
+ 0:
+ port:
+ 11:
+ dport_map_port: 1
+ 13:
+ dport_map_port: 2
+ 20:
+ dport_map_port: 3
+ 22:
+ dport_map_port: 4
+ 24:
+ dport_map_port: 5
+ 26:
+ dport_map_port: 6
+ 28:
+ dport_map_port: 7
+ 30:
+ dport_map_port: 8
+ 3:
+ dport_map_port: 9
+ 5:
+ dport_map_port: 10
+ 7:
+ dport_map_port: 11
+ 9:
+ dport_map_port: 12
+ 40:
+ dport_map_port: 13
+ 42:
+ dport_map_port: 14
+ 44:
+ dport_map_port: 15
+ 46:
+ dport_map_port: 16
+ 48:
+ dport_map_port: 17
+ 50:
+ dport_map_port: 18
+ 64:
+ dport_map_port: 19
+ 66:
+ dport_map_port: 20
+ 68:
+ dport_map_port: 21
+ 70:
+ dport_map_port: 22
+ 72:
+ dport_map_port: 23
+ 74:
+ dport_map_port: 24
+ 1:
+ dport_map_port: 25
+ 15:
+ dport_map_port: 26
+ 32:
+ dport_map_port: 27
+ 34:
+ dport_map_port: 28
+ 52:
+ dport_map_port: 29
+ 54:
+ dport_map_port: 30
+ 60:
+ dport_map_port: 31
+ 62:
+ dport_map_port: 32
+
+...
+
+---
+device:
+ 0:
+ DEVICE_CONFIG:
+ # CORE CLOCK FREQUENCY
+ CORE_CLK_FREQ: CLK_1350MHZ
+ # PP CLOCK FREQUENCY
+ PP_CLK_FREQ: CLK_1350MHZ
+...
+
+---
+device:
+ 0:
+ PC_PM_CORE:
+ ?
+ PC_PM_ID: 1
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x73510624
+ RX_LANE_MAP: 0x46270513
+ TX_POLARITY_FLIP: 0xa
+ RX_POLARITY_FLIP: 0x17
+ ?
+ PC_PM_ID: 2
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x52317046
+ RX_LANE_MAP: 0x31247056
+ TX_POLARITY_FLIP: 0x90
+ RX_POLARITY_FLIP: 0x47
+ ?
+ PC_PM_ID: 3
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x23104567
+ RX_LANE_MAP: 0x64752310
+ TX_POLARITY_FLIP: 0x29
+ RX_POLARITY_FLIP: 0x5a
+ ?
+ PC_PM_ID: 4
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x23104567
+ RX_LANE_MAP: 0x64752310
+ TX_POLARITY_FLIP: 0x29
+ RX_POLARITY_FLIP: 0x5a
+ ?
+ PC_PM_ID: 5
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x25047361
+ RX_LANE_MAP: 0x10452736
+ TX_POLARITY_FLIP: 0xf5
+ RX_POLARITY_FLIP: 0xc0
+ ?
+ PC_PM_ID: 6
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45763210
+ RX_LANE_MAP: 0x13026457
+ TX_POLARITY_FLIP: 0xa
+ RX_POLARITY_FLIP: 0xf9
+ ?
+ PC_PM_ID: 7
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45763210
+ RX_LANE_MAP: 0x13026457
+ TX_POLARITY_FLIP: 0xa
+ RX_POLARITY_FLIP: 0xf9
+ ?
+ PC_PM_ID: 8
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45673210
+ RX_LANE_MAP: 0x13026457
+ TX_POLARITY_FLIP: 0x4a
+ RX_POLARITY_FLIP: 0xf3
+ ?
+ PC_PM_ID: 9
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x02476531
+ RX_LANE_MAP: 0x05261734
+ TX_POLARITY_FLIP: 0xdf
+ RX_POLARITY_FLIP: 0x84
+ ?
+ PC_PM_ID: 10
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x37065241
+ RX_LANE_MAP: 0x04175263
+ TX_POLARITY_FLIP: 0x36
+ RX_POLARITY_FLIP: 0x39
+ ?
+ PC_PM_ID: 11
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x54762301
+ RX_LANE_MAP: 0x13025467
+ TX_POLARITY_FLIP: 0x70
+ RX_POLARITY_FLIP: 0x6f
+ ?
+ PC_PM_ID: 12
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x73125046
+ RX_LANE_MAP: 0x21437056
+ TX_POLARITY_FLIP: 0x78
+ RX_POLARITY_FLIP: 0x5c
+ ?
+ PC_PM_ID: 13
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x32104567
+ RX_LANE_MAP: 0x64572310
+ TX_POLARITY_FLIP: 0xd6
+ RX_POLARITY_FLIP: 0xad
+ ?
+ PC_PM_ID: 14
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x03172465
+ RX_LANE_MAP: 0x45173620
+ TX_POLARITY_FLIP: 0xed
+ RX_POLARITY_FLIP: 0x36
+ ?
+ PC_PM_ID: 15
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x36175042
+ RX_LANE_MAP: 0x04176253
+ TX_POLARITY_FLIP: 0x10
+ RX_POLARITY_FLIP: 0xfa
+ ?
+ PC_PM_ID: 16
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x74615203
+ RX_LANE_MAP: 0x51704236
+ TX_POLARITY_FLIP: 0x5f
+ RX_POLARITY_FLIP: 0x56
+ ?
+ PC_PM_ID: 17
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x26374051
+ RX_LANE_MAP: 0x37046251
+ TX_POLARITY_FLIP: 0xaa
+ RX_POLARITY_FLIP: 0x21
+ ?
+ PC_PM_ID: 18
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45672310
+ RX_LANE_MAP: 0x32105476
+ TX_POLARITY_FLIP: 0x15
+ RX_POLARITY_FLIP: 0x92
+ ?
+ PC_PM_ID: 19
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x70465321
+ RX_LANE_MAP: 0x63107542
+ TX_POLARITY_FLIP: 0xe6
+ RX_POLARITY_FLIP: 0xf2
+ ?
+ PC_PM_ID: 20
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x23015476
+ RX_LANE_MAP: 0x64752301
+ TX_POLARITY_FLIP: 0x50
+ RX_POLARITY_FLIP: 0x6c
+...
+
+---
+device:
+ 0:
+ PC_PORT_PHYS_MAP:
+ ?
+ # CPU port
+ PORT_ID: 0
+ :
+ PC_PHYS_PORT_ID: 0
+ ?
+ PORT_ID: 1
+ :
+ PC_PHYS_PORT_ID: 1
+ ?
+ PORT_ID: 3
+ :
+ PC_PHYS_PORT_ID: 9
+ ?
+ PORT_ID: 5
+ :
+ PC_PHYS_PORT_ID: 13
+ ?
+ PORT_ID: 7
+ :
+ PC_PHYS_PORT_ID: 17
+ ?
+ PORT_ID: 9
+ :
+ PC_PHYS_PORT_ID: 21
+ ?
+ PORT_ID: 11
+ :
+ PC_PHYS_PORT_ID: 25
+ ?
+ PORT_ID: 13
+ :
+ PC_PHYS_PORT_ID: 29
+ ?
+ PORT_ID: 15
+ :
+ PC_PHYS_PORT_ID: 33
+ ?
+ PORT_ID: 20
+ :
+ PC_PHYS_PORT_ID: 41
+ ?
+ PORT_ID: 22
+ :
+ PC_PHYS_PORT_ID: 45
+ ?
+ PORT_ID: 24
+ :
+ PC_PHYS_PORT_ID: 49
+ ?
+ PORT_ID: 26
+ :
+ PC_PHYS_PORT_ID: 53
+ ?
+ PORT_ID: 28
+ :
+ PC_PHYS_PORT_ID: 57
+ ?
+ PORT_ID: 30
+ :
+ PC_PHYS_PORT_ID: 61
+ ?
+ PORT_ID: 32
+ :
+ PC_PHYS_PORT_ID: 65
+ ?
+ PORT_ID: 34
+ :
+ PC_PHYS_PORT_ID: 73
+ ?
+ PORT_ID: 40
+ :
+ PC_PHYS_PORT_ID: 81
+ ?
+ PORT_ID: 42
+ :
+ PC_PHYS_PORT_ID: 85
+ ?
+ PORT_ID: 44
+ :
+ PC_PHYS_PORT_ID: 89
+ ?
+ PORT_ID: 46
+ :
+ PC_PHYS_PORT_ID: 93
+ ?
+ PORT_ID: 48
+ :
+ PC_PHYS_PORT_ID: 97
+ ?
+ PORT_ID: 50
+ :
+ PC_PHYS_PORT_ID: 101
+ ?
+ PORT_ID: 52
+ :
+ PC_PHYS_PORT_ID: 105
+ ?
+ PORT_ID: 54
+ :
+ PC_PHYS_PORT_ID: 113
+ ?
+ PORT_ID: 60
+ :
+ PC_PHYS_PORT_ID: 121
+ ?
+ PORT_ID: 62
+ :
+ PC_PHYS_PORT_ID: 129
+ ?
+ PORT_ID: 64
+ :
+ PC_PHYS_PORT_ID: 137
+ ?
+ PORT_ID: 66
+ :
+ PC_PHYS_PORT_ID: 141
+ ?
+ PORT_ID: 68
+ :
+ PC_PHYS_PORT_ID: 145
+ ?
+ PORT_ID: 70
+ :
+ PC_PHYS_PORT_ID: 149
+ ?
+ PORT_ID: 72
+ :
+ PC_PHYS_PORT_ID: 153
+ ?
+ PORT_ID: 74
+ :
+ PC_PHYS_PORT_ID: 157
+
+...
+
+---
+device:
+ 0:
+ PC_PORT:
+ ?
+ PORT_ID: 0
+ :
+ ENABLE: 1
+ SPEED: 10000
+ NUM_LANES: 1
+ ?
+ PORT_ID: [3, 5, 7, 9, 11, 13,
+ 20, 22, 24, 26, 28, 30,
+ 40, 42, 44, 46, 48, 50,
+ 64, 66, 68, 70, 72, 74]
+ :
+ ENABLE: 0
+ SPEED: 200000
+ FEC_MODE: PC_FEC_RS544_2XN
+ NUM_LANES: 4
+ LINK_TRAINING: 0
+ MAX_FRAME_SIZE: 9416
+ ?
+ PORT_ID: [1, 15, 32, 34, 52, 54, 60, 62]
+ :
+ ENABLE: 0
+ SPEED: 400000
+ FEC_MODE: PC_FEC_RS544_2XN
+ NUM_LANES: 8
+ LINK_TRAINING: 0
+ MAX_FRAME_SIZE: 9416
+
+...
+
+---
+device:
+ 0:
+ TM_SCHEDULER_CONFIG:
+ NUM_MC_Q: NUM_MC_Q_4
+...
+
+---
+device:
+ 0:
+ PC_TX_TAPS:
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 140
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 24
+ TX_PRE_SIGN: 1
+ TX_PRE2: 2
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 28
+ TX_PRE_SIGN: 1
+ TX_PRE2: 6
+...
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/td4-m2-w6520-24dc8qc-24x200G+8x400G.yml b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/td4-m2-w6520-24dc8qc-24x200G+8x400G.yml
new file mode 100644
index 000000000000..c4dd4e36d1ca
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/M2-W6520-24DC8QC/td4-m2-w6520-24dc8qc-24x200G+8x400G.yml
@@ -0,0 +1,4059 @@
+---
+bcm_device:
+ 0:
+ global:
+ bcm_tunnel_term_compatible_mode: 1
+ vlan_flooding_l2mc_num_reserved: 0
+ shared_block_mask_section: uc_bc
+ l3_alpm_template: 2
+ l3_alpm2_bnk_threshold: 100
+ svi_my_station_optimization: 1
+ uft_mode: 1
+ l3_enable: 1
+ l2_hitbit_enable: 0
+ pktio_mode: 1
+ sai_optimized_mmu: 1
+ warmboot_knet_shutdown_mode: 1
+...
+
+---
+device:
+ 0:
+ FP_CONFIG:
+ #FP_ING_OPERMODE: PIPE_UNIQUE
+ FP_ING_OPERMODE: GLOBAL_PIPE_AWARE
+...
+
+---
+bcm_device:
+ 0:
+ port:
+ 11:
+ dport_map_port: 1
+ 13:
+ dport_map_port: 2
+ 20:
+ dport_map_port: 3
+ 22:
+ dport_map_port: 4
+ 24:
+ dport_map_port: 5
+ 26:
+ dport_map_port: 6
+ 28:
+ dport_map_port: 7
+ 30:
+ dport_map_port: 8
+ 3:
+ dport_map_port: 9
+ 5:
+ dport_map_port: 10
+ 7:
+ dport_map_port: 11
+ 9:
+ dport_map_port: 12
+ 40:
+ dport_map_port: 13
+ 42:
+ dport_map_port: 14
+ 44:
+ dport_map_port: 15
+ 46:
+ dport_map_port: 16
+ 48:
+ dport_map_port: 17
+ 50:
+ dport_map_port: 18
+ 64:
+ dport_map_port: 19
+ 66:
+ dport_map_port: 20
+ 68:
+ dport_map_port: 21
+ 70:
+ dport_map_port: 22
+ 72:
+ dport_map_port: 23
+ 74:
+ dport_map_port: 24
+ 1:
+ dport_map_port: 25
+ 15:
+ dport_map_port: 26
+ 32:
+ dport_map_port: 27
+ 34:
+ dport_map_port: 28
+ 52:
+ dport_map_port: 29
+ 54:
+ dport_map_port: 30
+ 60:
+ dport_map_port: 31
+ 62:
+ dport_map_port: 32
+
+...
+
+---
+device:
+ 0:
+ DEVICE_CONFIG:
+ # CORE CLOCK FREQUENCY
+ CORE_CLK_FREQ: CLK_1350MHZ
+ # PP CLOCK FREQUENCY
+ PP_CLK_FREQ: CLK_1350MHZ
+...
+
+---
+device:
+ 0:
+ PC_PM_CORE:
+ ?
+ PC_PM_ID: 1
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x73510624
+ RX_LANE_MAP: 0x46270513
+ TX_POLARITY_FLIP: 0xa
+ RX_POLARITY_FLIP: 0x17
+ ?
+ PC_PM_ID: 2
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x52317046
+ RX_LANE_MAP: 0x31247056
+ TX_POLARITY_FLIP: 0x90
+ RX_POLARITY_FLIP: 0x47
+ ?
+ PC_PM_ID: 3
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x23104567
+ RX_LANE_MAP: 0x64752310
+ TX_POLARITY_FLIP: 0x29
+ RX_POLARITY_FLIP: 0x5a
+ ?
+ PC_PM_ID: 4
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x23104567
+ RX_LANE_MAP: 0x64752310
+ TX_POLARITY_FLIP: 0x29
+ RX_POLARITY_FLIP: 0x5a
+ ?
+ PC_PM_ID: 5
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x25047361
+ RX_LANE_MAP: 0x10452736
+ TX_POLARITY_FLIP: 0xf5
+ RX_POLARITY_FLIP: 0xc0
+ ?
+ PC_PM_ID: 6
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45763210
+ RX_LANE_MAP: 0x13026457
+ TX_POLARITY_FLIP: 0xa
+ RX_POLARITY_FLIP: 0xf9
+ ?
+ PC_PM_ID: 7
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45763210
+ RX_LANE_MAP: 0x13026457
+ TX_POLARITY_FLIP: 0xa
+ RX_POLARITY_FLIP: 0xf9
+ ?
+ PC_PM_ID: 8
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45673210
+ RX_LANE_MAP: 0x13026457
+ TX_POLARITY_FLIP: 0x4a
+ RX_POLARITY_FLIP: 0xf3
+ ?
+ PC_PM_ID: 9
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x02476531
+ RX_LANE_MAP: 0x05261734
+ TX_POLARITY_FLIP: 0xdf
+ RX_POLARITY_FLIP: 0x84
+ ?
+ PC_PM_ID: 10
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x37065241
+ RX_LANE_MAP: 0x04175263
+ TX_POLARITY_FLIP: 0x36
+ RX_POLARITY_FLIP: 0x39
+ ?
+ PC_PM_ID: 11
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x54762301
+ RX_LANE_MAP: 0x13025467
+ TX_POLARITY_FLIP: 0x70
+ RX_POLARITY_FLIP: 0x6f
+ ?
+ PC_PM_ID: 12
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x73125046
+ RX_LANE_MAP: 0x21437056
+ TX_POLARITY_FLIP: 0x78
+ RX_POLARITY_FLIP: 0x5c
+ ?
+ PC_PM_ID: 13
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x32104567
+ RX_LANE_MAP: 0x64572310
+ TX_POLARITY_FLIP: 0xd6
+ RX_POLARITY_FLIP: 0xad
+ ?
+ PC_PM_ID: 14
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x03172465
+ RX_LANE_MAP: 0x45173620
+ TX_POLARITY_FLIP: 0xed
+ RX_POLARITY_FLIP: 0x36
+ ?
+ PC_PM_ID: 15
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x36175042
+ RX_LANE_MAP: 0x04176253
+ TX_POLARITY_FLIP: 0x10
+ RX_POLARITY_FLIP: 0xfa
+ ?
+ PC_PM_ID: 16
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x74615203
+ RX_LANE_MAP: 0x51704236
+ TX_POLARITY_FLIP: 0x5f
+ RX_POLARITY_FLIP: 0x56
+ ?
+ PC_PM_ID: 17
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x26374051
+ RX_LANE_MAP: 0x37046251
+ TX_POLARITY_FLIP: 0xaa
+ RX_POLARITY_FLIP: 0x21
+ ?
+ PC_PM_ID: 18
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x45672310
+ RX_LANE_MAP: 0x32105476
+ TX_POLARITY_FLIP: 0x15
+ RX_POLARITY_FLIP: 0x92
+ ?
+ PC_PM_ID: 19
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x70465321
+ RX_LANE_MAP: 0x63107542
+ TX_POLARITY_FLIP: 0xe6
+ RX_POLARITY_FLIP: 0xf2
+ ?
+ PC_PM_ID: 20
+ CORE_INDEX: 0
+ :
+ TX_LANE_MAP_AUTO: 0
+ RX_LANE_MAP_AUTO: 0
+ TX_POLARITY_FLIP_AUTO: 0
+ RX_POLARITY_FLIP_AUTO: 0
+ TX_LANE_MAP: 0x23015476
+ RX_LANE_MAP: 0x64752301
+ TX_POLARITY_FLIP: 0x50
+ RX_POLARITY_FLIP: 0x6c
+...
+
+---
+device:
+ 0:
+ PC_PORT_PHYS_MAP:
+ ?
+ # CPU port
+ PORT_ID: 0
+ :
+ PC_PHYS_PORT_ID: 0
+ ?
+ PORT_ID: 1
+ :
+ PC_PHYS_PORT_ID: 1
+ ?
+ PORT_ID: 3
+ :
+ PC_PHYS_PORT_ID: 9
+ ?
+ PORT_ID: 5
+ :
+ PC_PHYS_PORT_ID: 13
+ ?
+ PORT_ID: 7
+ :
+ PC_PHYS_PORT_ID: 17
+ ?
+ PORT_ID: 9
+ :
+ PC_PHYS_PORT_ID: 21
+ ?
+ PORT_ID: 11
+ :
+ PC_PHYS_PORT_ID: 25
+ ?
+ PORT_ID: 13
+ :
+ PC_PHYS_PORT_ID: 29
+ ?
+ PORT_ID: 15
+ :
+ PC_PHYS_PORT_ID: 33
+ ?
+ PORT_ID: 20
+ :
+ PC_PHYS_PORT_ID: 41
+ ?
+ PORT_ID: 22
+ :
+ PC_PHYS_PORT_ID: 45
+ ?
+ PORT_ID: 24
+ :
+ PC_PHYS_PORT_ID: 49
+ ?
+ PORT_ID: 26
+ :
+ PC_PHYS_PORT_ID: 53
+ ?
+ PORT_ID: 28
+ :
+ PC_PHYS_PORT_ID: 57
+ ?
+ PORT_ID: 30
+ :
+ PC_PHYS_PORT_ID: 61
+ ?
+ PORT_ID: 32
+ :
+ PC_PHYS_PORT_ID: 65
+ ?
+ PORT_ID: 34
+ :
+ PC_PHYS_PORT_ID: 73
+ ?
+ PORT_ID: 40
+ :
+ PC_PHYS_PORT_ID: 81
+ ?
+ PORT_ID: 42
+ :
+ PC_PHYS_PORT_ID: 85
+ ?
+ PORT_ID: 44
+ :
+ PC_PHYS_PORT_ID: 89
+ ?
+ PORT_ID: 46
+ :
+ PC_PHYS_PORT_ID: 93
+ ?
+ PORT_ID: 48
+ :
+ PC_PHYS_PORT_ID: 97
+ ?
+ PORT_ID: 50
+ :
+ PC_PHYS_PORT_ID: 101
+ ?
+ PORT_ID: 52
+ :
+ PC_PHYS_PORT_ID: 105
+ ?
+ PORT_ID: 54
+ :
+ PC_PHYS_PORT_ID: 113
+ ?
+ PORT_ID: 60
+ :
+ PC_PHYS_PORT_ID: 121
+ ?
+ PORT_ID: 62
+ :
+ PC_PHYS_PORT_ID: 129
+ ?
+ PORT_ID: 64
+ :
+ PC_PHYS_PORT_ID: 137
+ ?
+ PORT_ID: 66
+ :
+ PC_PHYS_PORT_ID: 141
+ ?
+ PORT_ID: 68
+ :
+ PC_PHYS_PORT_ID: 145
+ ?
+ PORT_ID: 70
+ :
+ PC_PHYS_PORT_ID: 149
+ ?
+ PORT_ID: 72
+ :
+ PC_PHYS_PORT_ID: 153
+ ?
+ PORT_ID: 74
+ :
+ PC_PHYS_PORT_ID: 157
+
+...
+
+---
+device:
+ 0:
+ PC_PORT:
+ ?
+ PORT_ID: 0
+ :
+ ENABLE: 1
+ SPEED: 10000
+ NUM_LANES: 1
+ ?
+ PORT_ID: [3, 5, 7, 9, 11, 13,
+ 20, 22, 24, 26, 28, 30,
+ 40, 42, 44, 46, 48, 50,
+ 64, 66, 68, 70, 72, 74]
+ :
+ ENABLE: 0
+ SPEED: 200000
+ FEC_MODE: PC_FEC_RS544_2XN
+ NUM_LANES: 4
+ LINK_TRAINING: 0
+ MAX_FRAME_SIZE: 9416
+ ?
+ PORT_ID: [1, 15, 32, 34, 52, 54, 60, 62]
+ :
+ ENABLE: 0
+ SPEED: 400000
+ FEC_MODE: PC_FEC_RS544_2XN
+ NUM_LANES: 8
+ LINK_TRAINING: 0
+ MAX_FRAME_SIZE: 9416
+
+...
+
+---
+device:
+ 0:
+ TM_SCHEDULER_CONFIG:
+ NUM_MC_Q: NUM_MC_Q_4
+...
+
+---
+device:
+ 0:
+ PC_TX_TAPS:
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 14
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 11
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 13
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 20
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 22
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 24
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 26
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 28
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 30
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 3
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 5
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 7
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 9
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 40
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 42
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 44
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 46
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 48
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 50
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 4
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 64
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 66
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 16
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 68
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 16
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 70
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 72
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 74
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 148
+ TX_POST: 0
+ TX_POST_SIGN: 0
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 124
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 1
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 15
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 32
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 34
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 52
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 54
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 132
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 60
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [0]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [1]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [2]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [3]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [4]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [5]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 144
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [6]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 124
+ TX_POST: 8
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 8
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+ ?
+ PORT_ID: 62
+ LANE_INDEX: [7]
+ :
+ TX_SIG_MODE: PC_SIG_MODE_PAM4
+ TX_POST_AUTO: 0
+ TX_MAIN_AUTO: 0
+ TX_PRE_AUTO: 0
+ TX_PRE2_AUTO: 0
+ TX_POST2_AUTO: 0
+ TX_POST3_AUTO: 0
+ TX_AMP_AUTO: 0
+ TX_MAIN: 136
+ TX_POST: 12
+ TX_POST_SIGN: 1
+ TX_POST2: 0
+ TX_POST2_SIGN: 0
+ TX_POST3: 0
+ TX_POST3_SIGN: 0
+ TX_PRE: 12
+ TX_PRE_SIGN: 1
+ TX_PRE2: 0
+...
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/cpu.cint b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/cpu.cint
new file mode 100644
index 000000000000..e286d3cf42a6
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/cpu.cint
@@ -0,0 +1,85 @@
+cint_reset();
+
+int cint_field_group_create(int unit, bcm_field_group_t grp)
+{
+ int rv;
+
+ bcm_field_qset_t qset;
+ bcm_field_aset_t aset;
+
+ BCM_FIELD_QSET_INIT(qset);
+ BCM_FIELD_QSET_ADD(qset,bcmFieldQualifyDstMac);
+ BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyStageIngress);
+
+ BCM_FIELD_ASET_INIT(aset);
+ BCM_FIELD_ASET_ADD(aset, bcmFieldActionCopyToCpu);
+
+ rv = bcm_field_group_create_mode_id(unit, qset, 103, bcmFieldGroupModeAuto, grp);
+ if (rv != BCM_E_NONE) {
+ printf("bcm_field_group_create_mode_id failed, rv = %d\r\n", rv);
+ return -1;
+ }
+ printf("cint_field_group_create success!!!, rv = %d\r\n", rv);
+
+ bcm_field_group_dump(unit,grp);
+ return 0;
+}
+
+int cint_field_entry_create1(int unit, bcm_field_group_t grp,bcm_field_entry_t entry)
+{
+ int rv;
+ bcm_mac_t dst_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ bcm_mac_t mac_mask = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ rv = bcm_field_entry_create_id(unit, grp, entry);
+ if (rv != BCM_E_NONE) {
+ printf("bcm_field_entry_create_id failed, rv = %d\r\n", rv);
+ return -1;
+ }
+
+
+ rv =bcm_field_qualify_DstMac(unit, entry, dst_mac, mac_mask);
+ if (rv != BCM_E_NONE) {
+ printf("bcm_field_qualify_DstMac failed,ret = %d\r\n", rv);
+ bcm_field_entry_destroy(unit, entry);
+ return -1;
+ }
+
+ rv = bcm_field_action_add(unit, entry, bcmFieldActionCopyToCpu, 1, 0);
+ if (rv != BCM_E_NONE) {
+ printf("bcm_field_action_add failed, rv = %d \r\n", rv);
+ bcm_field_entry_destroy(unit, entry);
+ return -1;
+ }
+
+ rv = bcm_field_action_add(unit, entry, bcmFieldActionDrop, 1, 0);
+ if (rv != BCM_E_NONE) {
+ printf("bcm_field_action_add failed, rv = %d \r\n", rv);
+ bcm_field_entry_destroy(unit, entry);
+ return -1;
+ }
+
+ rv = bcm_field_entry_install(unit, entry);
+ if (rv != BCM_E_NONE) {
+ printf("bcm_field_entry_install failed,ret = %d\r\n", rv);
+ bcm_field_entry_destroy(unit, entry);
+ return -1;
+ }
+
+ printf("********************* BEGIN ****************************\r\n");
+ bcm_field_entry_dump(unit, entry);
+ printf("*********************** END ****************************\r\n");
+
+ return 0;
+}
+
+cint_field_group_create(0,5);
+cint_field_entry_create1(0,5,2048);
+
+//bcm_field_entry_destroy(0, 2048);
+//bcm_field_group_destroy(0, 5);
+
+
+
+
+
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/custom_led.bin b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/custom_led.bin
new file mode 100644
index 000000000000..34f9374b9878
Binary files /dev/null and b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/custom_led.bin differ
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/default_sku b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/default_sku
new file mode 100644
index 000000000000..afadd24f36c5
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/default_sku
@@ -0,0 +1 @@
+M2-W6520-24DC8QC l2
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/dev.xml b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/dev.xml
new file mode 100644
index 000000000000..e71ddf3237b3
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/dev.xml
@@ -0,0 +1,371 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/fru.py b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/fru.py
new file mode 100644
index 000000000000..f95164e03601
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/fru.py
@@ -0,0 +1,961 @@
+#!/usr/bin/python3
+import collections
+from datetime import datetime, timedelta
+from bitarray import bitarray
+
+
+__DEBUG__ = "N"
+
+
+class FruException(Exception):
+ def __init__(self, message='fruerror', code=-100):
+ err = 'errcode: {0} message:{1}'.format(code, message)
+ Exception.__init__(self, err)
+ self.code = code
+ self.message = message
+
+
+def e_print(err):
+ print("ERROR: " + err)
+
+
+def d_print(debug_info):
+ if __DEBUG__ == "Y":
+ print(debug_info)
+
+
+class FruUtil():
+ @staticmethod
+ def decodeLength(value):
+ a = bitarray(8)
+ a.setall(True)
+ a[0:1] = 0
+ a[1:2] = 0
+ x = ord(a.tobytes())
+ return x & ord(value)
+
+ @staticmethod
+ def minToData():
+ starttime = datetime(1996, 1, 1, 0, 0, 0)
+ endtime = datetime.now()
+ seconds = (endtime - starttime).total_seconds()
+ mins = seconds // 60
+ m = int(round(mins))
+ return m
+
+ @staticmethod
+ def getTimeFormat():
+ return datetime.now().strftime('%Y-%m-%d')
+
+ @staticmethod
+ def getTypeLength(value):
+ if value is None or len(value) == 0:
+ return 0
+ a = bitarray(8)
+ a.setall(False)
+ a[0:1] = 1
+ a[1:2] = 1
+ x = ord(a.tobytes())
+ return x | len(value)
+
+ @staticmethod
+ def checksum(b):
+ result = 0
+ for item in b:
+ result += ord(item)
+ return (0x100 - (result & 0xff)) & 0xff
+
+
+class BaseArea(object):
+ SUGGESTED_SIZE_COMMON_HEADER = 8
+ SUGGESTED_SIZE_INTERNAL_USE_AREA = 72
+ SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32
+ SUGGESTED_SIZE_BOARD_INFO_AREA = 80
+ SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80
+
+ INITVALUE = b'\x00'
+ resultvalue = INITVALUE * 256
+ COMMON_HEAD_VERSION = b'\x01'
+ __childList = None
+
+ def __init__(self, name="", size=0, offset=0):
+ self.__childList = []
+ self._offset = offset
+ self.name = name
+ self._size = size
+ self._isPresent = False
+ self._data = b'\x00' * size
+
+ @property
+ def childList(self):
+ return self.__childList
+
+ @childList.setter
+ def childList(self, value):
+ self.__childList = value
+
+ @property
+ def offset(self):
+ return self._offset
+
+ @offset.setter
+ def offset(self, value):
+ self._offset = value
+
+ @property
+ def size(self):
+ return self._size
+
+ @size.setter
+ def size(self, value):
+ self._size = value
+
+ @property
+ def data(self):
+ return self._data
+
+ @data.setter
+ def data(self, value):
+ self._data = value
+
+ @property
+ def isPresent(self):
+ return self._isPresent
+
+ @isPresent.setter
+ def isPresent(self, value):
+ self._isPresent = value
+
+
+class InternalUseArea(BaseArea):
+ pass
+
+
+class ChassisInfoArea(BaseArea):
+ pass
+
+
+class BoardInfoArea(BaseArea):
+ _boardTime = None
+ _fields = None
+ _mfg_date = None
+ areaversion = None
+ _boardversion = None
+ _language = None
+
+ def __str__(self):
+ formatstr = "version : %x\n" \
+ "length : %d \n" \
+ "language : %x \n" \
+ "mfg_date : %s \n" \
+ "boardManufacturer : %s \n" \
+ "boardProductName : %s \n" \
+ "boardSerialNumber : %s \n" \
+ "boardPartNumber : %s \n" \
+ "fruFileId : %s \n"
+
+ tmpstr = formatstr % (ord(self.boardversion), self.size,
+ self.language, self.getMfgRealData(),
+ self.boardManufacturer, self.boardProductName,
+ self.boardSerialNumber, self.boardPartNumber,
+ self.fruFileId)
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ tmpstr += "boardextra%d : %s \n" % (i, valtmpval)
+ else:
+ break
+
+ return tmpstr
+
+ def todict(self):
+ dic = collections.OrderedDict()
+ dic["boardversion"] = ord(self.boardversion)
+ dic["boardlength"] = self.size
+ dic["boardlanguage"] = self.language
+ dic["boardmfg_date"] = self.getMfgRealData()
+ dic["boardManufacturer"] = self.boardManufacturer
+ dic["boardProductName"] = self.boardProductName
+ dic["boardSerialNumber"] = self.boardSerialNumber
+ dic["boardPartNumber"] = self.boardPartNumber
+ dic["boardfruFileId"] = self.fruFileId
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ dic[valtmp] = valtmpval
+ else:
+ break
+ return dic
+
+ def decodedata(self):
+ index = 0
+ self.areaversion = self.data[index]
+ index += 1
+ d_print("decode length :%d class size:%d" %
+ ((ord(self.data[index]) * 8), self.size))
+ index += 2
+
+ timetmp = self.data[index: index + 3]
+ self.mfg_date = ord(timetmp[0]) | (
+ ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16)
+ d_print("decode getMfgRealData :%s" % self.getMfgRealData())
+ index += 3
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardManufacturer = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardManufacturer:%s" % self.boardManufacturer)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardProductName = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardProductName:%s" % self.boardProductName)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardSerialNumber = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardSerialNumber:%s" % self.boardSerialNumber)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardPartNumber = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardPartNumber:%s" % self.boardPartNumber)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.fruFileId = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode fruFileId:%s" % self.fruFileId)
+
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if self.data[index] != chr(0xc1):
+ templen = FruUtil.decodeLength(self.data[index])
+ tmpval = self.data[index + 1: index + templen + 1]
+ setattr(self, valtmp, tmpval)
+ index += templen + 1
+ d_print("decode boardextra%d:%s" % (i, tmpval))
+ else:
+ break
+
+ def fruSetValue(self, field, value):
+ tmp_field = getattr(self, field, None)
+ if tmp_field is not None:
+ setattr(self, field, value)
+
+ def recalcute(self):
+ d_print("boardInfoArea version:%x" % ord(self.boardversion))
+ d_print("boardInfoArea length:%d" % self.size)
+ d_print("boardInfoArea language:%x" % self.language)
+ self.mfg_date = FruUtil.minToData()
+ d_print("boardInfoArea mfg_date:%x" % self.mfg_date)
+
+ self.data = chr(ord(self.boardversion)) + \
+ chr(self.size // 8) + chr(self.language)
+
+ self.data += chr(self.mfg_date & 0xFF)
+ self.data += chr((self.mfg_date >> 8) & 0xFF)
+ self.data += chr((self.mfg_date >> 16) & 0xFF)
+
+ d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer)
+ typelength = FruUtil.getTypeLength(self.boardManufacturer)
+ self.data += chr(typelength)
+ self.data += self.boardManufacturer
+
+ d_print("boardInfoArea boardProductName:%s" % self.boardProductName)
+ self.data += chr(FruUtil.getTypeLength(self.boardProductName))
+ self.data += self.boardProductName
+
+ d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber)
+ self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber))
+ self.data += self.boardSerialNumber
+
+ d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber)
+ self.data += chr(FruUtil.getTypeLength(self.boardPartNumber))
+ self.data += self.boardPartNumber
+
+ d_print("boardInfoArea fruFileId:%s" % self.fruFileId)
+ self.data += chr(FruUtil.getTypeLength(self.fruFileId))
+ self.data += self.fruFileId
+
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval))
+ self.data += chr(FruUtil.getTypeLength(valtmpval))
+ if valtmpval is not None:
+ self.data += valtmpval
+ else:
+ break
+
+ self.data += chr(0xc1)
+
+ if len(self.data) > (self.size - 1):
+ incr = (len(self.data) - self.size) // 8 + 1
+ self.size += incr * 8
+
+ self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:]
+ d_print("self data:%d" % len(self.data))
+ d_print("self size:%d" % self.size)
+ d_print("adjust size:%d" % (self.size - len(self.data) - 1))
+ self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0]))
+
+ # checksum
+ checksum = FruUtil.checksum(self.data)
+ d_print("board info checksum:%x" % checksum)
+ self.data += chr(checksum)
+
+ def getMfgRealData(self):
+ starttime = datetime(1996, 1, 1, 0, 0, 0)
+ mactime = starttime + timedelta(minutes=self.mfg_date)
+ return mactime
+
+ @property
+ def language(self):
+ self._language = 25
+ return self._language
+
+ @property
+ def mfg_date(self):
+ return self._mfg_date
+
+ @mfg_date.setter
+ def mfg_date(self, val):
+ self._mfg_date = val
+
+ @property
+ def boardversion(self):
+ self._boardversion = self.COMMON_HEAD_VERSION
+ return self._boardversion
+
+ @property
+ def fruFileId(self):
+ return self._FRUFileID
+
+ @fruFileId.setter
+ def fruFileId(self, val):
+ self._FRUFileID = val
+
+ @property
+ def boardPartNumber(self):
+ return self._boardPartNumber
+
+ @boardPartNumber.setter
+ def boardPartNumber(self, val):
+ self._boardPartNumber = val
+
+ @property
+ def boardSerialNumber(self):
+ return self._boardSerialNumber
+
+ @boardSerialNumber.setter
+ def boardSerialNumber(self, val):
+ self._boardSerialNumber = val
+
+ @property
+ def boardProductName(self):
+ return self._boradProductName
+
+ @boardProductName.setter
+ def boardProductName(self, val):
+ self._boradProductName = val
+
+ @property
+ def boardManufacturer(self):
+ return self._boardManufacturer
+
+ @boardManufacturer.setter
+ def boardManufacturer(self, val):
+ self._boardManufacturer = val
+
+ @property
+ def boardTime(self):
+ return self._boardTime
+
+ @boardTime.setter
+ def boardTime(self, val):
+ self._boardTime = val
+
+ @property
+ def fields(self):
+ return self._fields
+
+ @fields.setter
+ def fields(self, val):
+ self._fields = val
+
+
+class ProductInfoArea(BaseArea):
+ _productManufacturer = None
+ _productAssetTag = None
+ _FRUFileID = None
+ _language = None
+
+ def __str__(self):
+ formatstr = "version : %x\n" \
+ "length : %d \n" \
+ "language : %x \n" \
+ "productManufacturer : %s \n" \
+ "productName : %s \n" \
+ "productPartModelName: %s \n" \
+ "productVersion : %s \n" \
+ "productSerialNumber : %s \n" \
+ "productAssetTag : %s \n" \
+ "fruFileId : %s \n"
+
+ tmpstr = formatstr % (ord(self.areaversion), self.size,
+ self.language, self.productManufacturer,
+ self.productName, self.productPartModelName,
+ self.productVersion, self.productSerialNumber,
+ self.productAssetTag, self.fruFileId)
+
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ tmpstr += "productextra%d : %s \n" % (i, valtmpval)
+ else:
+ break
+
+ return tmpstr
+
+ def todict(self):
+ dic = collections.OrderedDict()
+ dic["productversion"] = ord(self.areaversion)
+ dic["productlength"] = self.size
+ dic["productlanguage"] = self.language
+ dic["productManufacturer"] = self.productManufacturer
+ dic["productName"] = self.productName
+ dic["productPartModelName"] = self.productPartModelName
+ dic["productVersion"] = int(self.productVersion, 16)
+ dic["productSerialNumber"] = self.productSerialNumber
+ dic["productAssetTag"] = self.productAssetTag
+ dic["productfruFileId"] = self.fruFileId
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ dic[valtmp] = valtmpval
+ else:
+ break
+ return dic
+
+ def decodedata(self):
+ index = 0
+ self.areaversion = self.data[index] # 0
+ index += 1
+ d_print("decode length %d" % (ord(self.data[index]) * 8))
+ d_print("class size %d" % self.size)
+ index += 2
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productManufacturer = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productManufacturer:%s" % self.productManufacturer)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productName = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productName:%s" % self.productName)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productPartModelName = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productPartModelName:%s" % self.productPartModelName)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productVersion = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productVersion:%s" % self.productVersion)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productSerialNumber = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productSerialNumber:%s" % self.productSerialNumber)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productAssetTag = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productAssetTag:%s" % self.productAssetTag)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.fruFileId = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode fruFileId:%s" % self.fruFileId)
+
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if self.data[index] != chr(0xc1) and index < self.size - 1:
+ templen = FruUtil.decodeLength(self.data[index])
+ if templen == 0:
+ break
+ tmpval = self.data[index + 1: index + templen + 1]
+ d_print("decode boardextra%d:%s" % (i, tmpval))
+ setattr(self, valtmp, tmpval)
+ index += templen + 1
+ else:
+ break
+
+ @property
+ def productVersion(self):
+ return self._productVersion
+
+ @productVersion.setter
+ def productVersion(self, name):
+ self._productVersion = name
+
+ @property
+ def areaversion(self):
+ self._areaversion = self.COMMON_HEAD_VERSION
+ return self._areaversion
+
+ @areaversion.setter
+ def areaversion(self, name):
+ self._areaversion = name
+
+ @property
+ def language(self):
+ self._language = 25
+ return self._language
+
+ @property
+ def productManufacturer(self):
+ return self._productManufacturer
+
+ @productManufacturer.setter
+ def productManufacturer(self, name):
+ self._productManufacturer = name
+
+ @property
+ def productName(self):
+ return self._productName
+
+ @productName.setter
+ def productName(self, name):
+ self._productName = name
+
+ @property
+ def productPartModelName(self):
+ return self._productPartModelName
+
+ @productPartModelName.setter
+ def productPartModelName(self, name):
+ self._productPartModelName = name
+
+ @property
+ def productSerialNumber(self):
+ return self._productSerialNumber
+
+ @productSerialNumber.setter
+ def productSerialNumber(self, name):
+ self._productSerialNumber = name
+
+ @property
+ def productAssetTag(self):
+ return self._productAssetTag
+
+ @productAssetTag.setter
+ def productAssetTag(self, name):
+ self._productAssetTag = name
+
+ @property
+ def fruFileId(self):
+ return self._FRUFileID
+
+ @fruFileId.setter
+ def fruFileId(self, name):
+ self._FRUFileID = name
+
+ def fruSetValue(self, field, value):
+ tmp_field = getattr(self, field, None)
+ if tmp_field is not None:
+ setattr(self, field, value)
+
+ def recalcute(self):
+ d_print("product version:%x" % ord(self.areaversion))
+ d_print("product length:%d" % self.size)
+ d_print("product language:%x" % self.language)
+ self.data = chr(ord(self.areaversion)) + \
+ chr(self.size // 8) + chr(self.language)
+
+ typelength = FruUtil.getTypeLength(self.productManufacturer)
+ self.data += chr(typelength)
+ self.data += self.productManufacturer
+
+ self.data += chr(FruUtil.getTypeLength(self.productName))
+ self.data += self.productName
+
+ self.data += chr(FruUtil.getTypeLength(self.productPartModelName))
+ self.data += self.productPartModelName
+
+ self.data += chr(FruUtil.getTypeLength(self.productVersion))
+ self.data += self.productVersion
+
+ self.data += chr(FruUtil.getTypeLength(self.productSerialNumber))
+ self.data += self.productSerialNumber
+
+ self.data += chr(FruUtil.getTypeLength(self.productAssetTag))
+ if self.productAssetTag is not None:
+ self.data += self.productAssetTag
+
+ self.data += chr(FruUtil.getTypeLength(self.fruFileId))
+ self.data += self.fruFileId
+
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ d_print("boardInfoArea productextra%d:%s" % (i, valtmpval))
+ self.data += chr(FruUtil.getTypeLength(valtmpval))
+ if valtmpval is not None:
+ self.data += valtmpval
+ else:
+ break
+
+ self.data += chr(0xc1)
+ if len(self.data) > (self.size - 1):
+ incr = (len(self.data) - self.size) // 8 + 1
+ self.size += incr * 8
+ d_print("self.data:%d" % len(self.data))
+ d_print("self.size:%d" % self.size)
+
+ self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:]
+ self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0]))
+ checksum = FruUtil.checksum(self.data)
+ d_print("board info checksum:%x" % checksum)
+ self.data += chr(checksum)
+
+
+class MultiRecordArea(BaseArea):
+ pass
+
+
+class Field(object):
+
+ def __init__(self, fieldType="ASCII", fieldData=""):
+ self.fieldData = fieldData
+ self.fieldType = fieldType
+
+ @property
+ def fieldType(self):
+ return self.fieldType
+
+ @property
+ def fieldData(self):
+ return self.fieldData
+
+
+class ipmifru(BaseArea):
+ _BoardInfoArea = None
+ _ProductInfoArea = None
+ _InternalUseArea = None
+ _ChassisInfoArea = None
+ _multiRecordArea = None
+ _productinfoAreaOffset = BaseArea.INITVALUE
+ _boardInfoAreaOffset = BaseArea.INITVALUE
+ _internalUserAreaOffset = BaseArea.INITVALUE
+ _chassicInfoAreaOffset = BaseArea.INITVALUE
+ _multiRecordAreaOffset = BaseArea.INITVALUE
+ _bindata = None
+ _bodybin = None
+ _version = BaseArea.COMMON_HEAD_VERSION
+ _zeroCheckSum = None
+ _frusize = 256
+
+ def __str__(self):
+ tmpstr = ""
+ if self.boardInfoArea.isPresent:
+ tmpstr += "\nboardinfoarea: \n"
+ tmpstr += self.boardInfoArea.__str__()
+ if self.productInfoArea.isPresent:
+ tmpstr += "\nproductinfoarea: \n"
+ tmpstr += self.productInfoArea.__str__()
+ return tmpstr
+
+ def decodeBin(self, eeprom):
+ commonHead = eeprom[0:8]
+ d_print("decode version %x" % ord(commonHead[0]))
+ if ord(self.COMMON_HEAD_VERSION) != ord(commonHead[0]):
+ raise FruException("HEAD VERSION error,not Fru format!", -10)
+ if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]):
+ strtemp = "check header checksum error [cal:%02x data:%02x]" % (
+ FruUtil.checksum(commonHead[0:7]), ord(commonHead[7]))
+ raise FruException(strtemp, -3)
+ if ord(commonHead[1]) != ord(self.INITVALUE):
+ d_print("Internal Use Area is present")
+ self.internalUseArea = InternalUseArea(
+ name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA)
+ self.internalUseArea.isPresent = True
+ self.internalUserAreaOffset = ord(commonHead[1])
+ self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: (
+ self.internalUserAreaOffset * 8 + self.internalUseArea.size)]
+ if ord(commonHead[2]) != ord(self.INITVALUE):
+ d_print("Chassis Info Area is present")
+ self.chassisInfoArea = ChassisInfoArea(
+ name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA)
+ self.chassisInfoArea.isPresent = True
+ self.chassicInfoAreaOffset = ord(commonHead[2])
+ self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: (
+ self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)]
+ if ord(commonHead[3]) != ord(self.INITVALUE):
+ self.boardInfoArea = BoardInfoArea(
+ name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA)
+ self.boardInfoArea.isPresent = True
+ self.boardInfoAreaOffset = ord(commonHead[3])
+ self.boardInfoArea.size = ord(
+ eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8
+ d_print("Board Info Area is present size:%d" %
+ (self.boardInfoArea.size))
+ self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: (
+ self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)]
+ if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]):
+ strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" % \
+ (FruUtil.checksum(
+ self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:]))
+ raise FruException(strtmp, -3)
+ self.boardInfoArea.decodedata()
+ if ord(commonHead[4]) != ord(self.INITVALUE):
+ d_print("Product Info Area is present")
+ self.productInfoArea = ProductInfoArea(
+ name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA)
+ self.productInfoArea.isPresent = True
+ self.productinfoAreaOffset = ord(commonHead[4])
+ d_print("length offset value: %02x" %
+ ord(eeprom[self.productinfoAreaOffset * 8 + 1]))
+ self.productInfoArea.size = ord(
+ eeprom[self.productinfoAreaOffset * 8 + 1]) * 8
+ d_print("Product Info Area is present size:%d" %
+ (self.productInfoArea.size))
+
+ self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: (
+ self.productinfoAreaOffset * 8 + self.productInfoArea.size)]
+ if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]):
+ strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % (
+ FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:]))
+ raise FruException(strtmp, -3)
+ self.productInfoArea.decodedata()
+ if ord(commonHead[5]) != ord(self.INITVALUE):
+ self.multiRecordArea = MultiRecordArea(
+ name="MultiRecord record Area ")
+ d_print("MultiRecord record present")
+ self.multiRecordArea.isPresent = True
+ self.multiRecordAreaOffset = ord(commonHead[5])
+ self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: (
+ self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)]
+
+ def initDefault(self):
+ self.version = self.COMMON_HEAD_VERSION
+ self.internalUserAreaOffset = self.INITVALUE
+ self.chassicInfoAreaOffset = self.INITVALUE
+ self.boardInfoAreaOffset = self.INITVALUE
+ self.productinfoAreaOffset = self.INITVALUE
+ self.multiRecordAreaOffset = self.INITVALUE
+ self.zeroCheckSum = self.INITVALUE
+ self.offset = self.SUGGESTED_SIZE_COMMON_HEADER
+ self.productInfoArea = None
+ self.internalUseArea = None
+ self.boardInfoArea = None
+ self.chassisInfoArea = None
+ self.multiRecordArea = None
+ # self.recalcute()
+
+ @property
+ def version(self):
+ return self._version
+
+ @version.setter
+ def version(self, name):
+ self._version = name
+
+ @property
+ def internalUserAreaOffset(self):
+ return self._internalUserAreaOffset
+
+ @internalUserAreaOffset.setter
+ def internalUserAreaOffset(self, obj):
+ self._internalUserAreaOffset = obj
+
+ @property
+ def chassicInfoAreaOffset(self):
+ return self._chassicInfoAreaOffset
+
+ @chassicInfoAreaOffset.setter
+ def chassicInfoAreaOffset(self, obj):
+ self._chassicInfoAreaOffset = obj
+
+ @property
+ def productinfoAreaOffset(self):
+ return self._productinfoAreaOffset
+
+ @productinfoAreaOffset.setter
+ def productinfoAreaOffset(self, obj):
+ self._productinfoAreaOffset = obj
+
+ @property
+ def boardInfoAreaOffset(self):
+ return self._boardInfoAreaOffset
+
+ @boardInfoAreaOffset.setter
+ def boardInfoAreaOffset(self, obj):
+ self._boardInfoAreaOffset = obj
+
+ @property
+ def multiRecordAreaOffset(self):
+ return self._multiRecordAreaOffset
+
+ @multiRecordAreaOffset.setter
+ def multiRecordAreaOffset(self, obj):
+ self._multiRecordAreaOffset = obj
+
+ @property
+ def zeroCheckSum(self):
+ return self._zeroCheckSum
+
+ @zeroCheckSum.setter
+ def zeroCheckSum(self, obj):
+ self._zeroCheckSum = obj
+
+ @property
+ def productInfoArea(self):
+ return self._ProductInfoArea
+
+ @productInfoArea.setter
+ def productInfoArea(self, obj):
+ self._ProductInfoArea = obj
+
+ @property
+ def internalUseArea(self):
+ return self._InternalUseArea
+
+ @internalUseArea.setter
+ def internalUseArea(self, obj):
+ self.internalUseArea = obj
+
+ @property
+ def boardInfoArea(self):
+ return self._BoardInfoArea
+
+ @boardInfoArea.setter
+ def boardInfoArea(self, obj):
+ self._BoardInfoArea = obj
+
+ @property
+ def chassisInfoArea(self):
+ return self._ChassisInfoArea
+
+ @chassisInfoArea.setter
+ def chassisInfoArea(self, obj):
+ self._ChassisInfoArea = obj
+
+ @property
+ def multiRecordArea(self):
+ return self._multiRecordArea
+
+ @multiRecordArea.setter
+ def multiRecordArea(self, obj):
+ self._multiRecordArea = obj
+
+ @property
+ def bindata(self):
+ return self._bindata
+
+ @bindata.setter
+ def bindata(self, obj):
+ self._bindata = obj
+
+ @property
+ def bodybin(self):
+ return self._bodybin
+
+ @bodybin.setter
+ def bodybin(self, obj):
+ self._bodybin = obj
+
+ def recalcuteCommonHead(self):
+ self.bindata = ""
+ self.offset = self.SUGGESTED_SIZE_COMMON_HEADER
+ d_print("common Header %d" % self.offset)
+ d_print("fru eeprom size %d" % self._frusize)
+ if self.internalUseArea is not None and self.internalUseArea.isPresent:
+ self.internalUserAreaOffset = self.offset // 8
+ self.offset += self.internalUseArea.size
+ d_print("internalUseArea is present offset:%d" % self.offset)
+
+ if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent:
+ self.chassicInfoAreaOffset = self.offset // 8
+ self.offset += self.chassisInfoArea.size
+ d_print("chassisInfoArea is present offset:%d" % self.offset)
+
+ if self.boardInfoArea is not None and self.boardInfoArea.isPresent:
+ self.boardInfoAreaOffset = self.offset // 8
+ self.offset += self.boardInfoArea.size
+ d_print("boardInfoArea is present offset:%d" % self.offset)
+ d_print("boardInfoArea is present size:%d" %
+ self.boardInfoArea.size)
+
+ if self.productInfoArea is not None and self.productInfoArea.isPresent:
+ self.productinfoAreaOffset = self.offset // 8
+ self.offset += self.productInfoArea.size
+ d_print("productInfoArea is present offset:%d" % self.offset)
+
+ if self.multiRecordArea is not None and self.multiRecordArea.isPresent:
+ self.multiRecordAreaOffset = self.offset // 8
+ d_print("multiRecordArea is present offset:%d" % self.offset)
+
+ if self.internalUserAreaOffset == self.INITVALUE:
+ self.internalUserAreaOffset = 0
+ if self.productinfoAreaOffset == self.INITVALUE:
+ self.productinfoAreaOffset = 0
+ if self.chassicInfoAreaOffset == self.INITVALUE:
+ self.chassicInfoAreaOffset = 0
+ if self.boardInfoAreaOffset == self.INITVALUE:
+ self.boardInfoAreaOffset = 0
+ if self.multiRecordAreaOffset == self.INITVALUE:
+ self.multiRecordAreaOffset = 0
+
+ self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset
+ - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff
+ d_print("zerochecksum:%x" % self.zeroCheckSum)
+ self.data = ""
+ self.data += chr(self.version[0]) + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr(
+ self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + chr(self.INITVALUE[0]) + chr(self.zeroCheckSum)
+
+ self.bindata = self.data + self.bodybin
+ totallen = len(self.bindata)
+ d_print("totallen %d" % totallen)
+ if totallen < self._frusize:
+ self.bindata = self.bindata.ljust(self._frusize, chr(self.INITVALUE[0]))
+ else:
+ raise FruException('bin data more than %d' % self._frusize, -2)
+
+ def recalcutebin(self):
+ self.bodybin = ""
+ if self.internalUseArea is not None and self.internalUseArea.isPresent:
+ d_print("internalUseArea present")
+ self.bodybin += self.internalUseArea.data
+ if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent:
+ d_print("chassisInfoArea present")
+ self.bodybin += self.chassisInfoArea.data
+ if self.boardInfoArea is not None and self.boardInfoArea.isPresent:
+ d_print("boardInfoArea present")
+ self.boardInfoArea.recalcute()
+ self.bodybin += self.boardInfoArea.data
+ if self.productInfoArea is not None and self.productInfoArea.isPresent:
+ d_print("productInfoAreapresent")
+ self.productInfoArea.recalcute()
+ self.bodybin += self.productInfoArea.data
+ if self.multiRecordArea is not None and self.multiRecordArea.isPresent:
+ d_print("multiRecordArea present")
+ self.bodybin += self.productInfoArea.data
+
+ def recalcute(self, fru_eeprom_size=256):
+ self._frusize = fru_eeprom_size
+ self.recalcutebin()
+ self.recalcuteCommonHead()
+
+ def setValue(self, area, field, value):
+ tmp_area = getattr(self, area, None)
+ if tmp_area is not None:
+ tmp_area.fruSetValue(field, value)
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/hwsku.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/hwsku.json
new file mode 100644
index 000000000000..0992d683af0b
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/hwsku.json
@@ -0,0 +1,100 @@
+{
+ "interfaces": {
+ "Ethernet1": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet2": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet3": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet4": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet5": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet6": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet7": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet8": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet9": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet10": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet11": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet12": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet13": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet14": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet15": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet16": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet17": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet18": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet19": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet20": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet21": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet22": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet23": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet24": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet25": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet33": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet41": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet49": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet57": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet65": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet73": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet81": {
+ "default_brkout_mode": "1x400G"
+ }
+ }
+}
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/installer.conf b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/installer.conf
new file mode 100644
index 000000000000..2a5d7d83f102
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/installer.conf
@@ -0,0 +1,2 @@
+CONSOLE_SPEED=115200
+ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_idle.max_cstate=0 idle=poll modprobe.blacklist=spi_intel,spi_intel_platform,spi_intel_pci"
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/led_proc_init.soc b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/led_proc_init.soc
new file mode 100644
index 000000000000..6167c3d68f33
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/led_proc_init.soc
@@ -0,0 +1,7 @@
+led load /usr/share/sonic/platform/custom_led.bin
+
+led auto on
+
+led start
+
+linkscan SwPortBitMap=xe,ce,cd
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/media_settings.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/media_settings.json
new file mode 100644
index 000000000000..be66be697b7d
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/media_settings.json
@@ -0,0 +1,2692 @@
+{
+ "PORT_MEDIA_SETTINGS": {
+ "0": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000084",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff2",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "1": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "2": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "3": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "4": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "5": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "6": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "7": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffa",
+ "lane1": "0xfffffffa",
+ "lane2": "0xfffffffa",
+ "lane3": "0xfffffffa"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "8": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000084",
+ "lane2": "0x00000084",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "9": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "10": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "11": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000084",
+ "lane1": "0x00000084",
+ "lane2": "0x00000084",
+ "lane3": "0x00000084"
+ },
+ "post1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "12": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000084",
+ "lane1": "0x00000084",
+ "lane2": "0x00000084",
+ "lane3": "0x00000084"
+ },
+ "post1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "13": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffffc",
+ "lane1": "0xfffffffc",
+ "lane2": "0xfffffffc",
+ "lane3": "0xfffffffc"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "14": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffffc",
+ "lane1": "0xfffffffc",
+ "lane2": "0xfffffffc",
+ "lane3": "0xfffffffc"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "15": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffe",
+ "lane1": "0xfffffffe",
+ "lane2": "0xfffffffe",
+ "lane3": "0xfffffffe"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffffc",
+ "lane1": "0xfffffffc",
+ "lane2": "0xfffffffc",
+ "lane3": "0xfffffffc"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "16": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffffc",
+ "lane1": "0xfffffffc",
+ "lane2": "0xfffffffc",
+ "lane3": "0xfffffffc"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "17": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffffc",
+ "lane1": "0xfffffffc",
+ "lane2": "0xfffffffc",
+ "lane3": "0xfffffffc"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "18": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffffc",
+ "lane2": "0xfffffffc",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "19": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "20": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000088",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff0",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff0"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "21": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "22": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000088",
+ "lane1": "0x00000088",
+ "lane2": "0x00000088",
+ "lane3": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "23": {
+ "QSFP28-": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "main": {
+ "lane0": "0x00000084",
+ "lane1": "0x00000084",
+ "lane2": "0x00000084",
+ "lane3": "0x00000084"
+ },
+ "post1": {
+ "lane0": "0xfffffff8",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff8",
+ "lane3": "0xfffffff8"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ }
+ },
+ "24": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff8",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000094",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000088",
+ "lane5": "0x00000090",
+ "lane6": "0x0000007C",
+ "lane7": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0x00000000",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff8",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ },
+ "25": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000090",
+ "lane5": "0x00000090",
+ "lane6": "0x00000090",
+ "lane7": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ },
+ "26": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff8",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000090",
+ "lane5": "0x00000090",
+ "lane6": "0x00000088",
+ "lane7": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ },
+ "27": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000090",
+ "lane5": "0x00000090",
+ "lane6": "0x00000090",
+ "lane7": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ },
+ "28": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000090",
+ "lane5": "0x00000090",
+ "lane6": "0x00000090",
+ "lane7": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ },
+ "29": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000090",
+ "lane5": "0x00000090",
+ "lane6": "0x00000090",
+ "lane7": "0x00000090"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ },
+ "30": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff8",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000090",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000084",
+ "lane5": "0x00000090",
+ "lane6": "0x00000090",
+ "lane7": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff4",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff8",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff4",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ },
+ "31": {
+ "QSFP28": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "main": {
+ "lane0": "0x00000057",
+ "lane1": "0x00000057",
+ "lane2": "0x00000057",
+ "lane3": "0x00000057"
+ },
+ "post1": {
+ "lane0": "0xfffffffb",
+ "lane1": "0xfffffffb",
+ "lane2": "0xfffffffb",
+ "lane3": "0xfffffffb"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000"
+ }
+ },
+ "Default": {
+ "pre2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "pre1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff8",
+ "lane7": "0xfffffff4"
+ },
+ "main": {
+ "lane0": "0x00000090",
+ "lane1": "0x00000088",
+ "lane2": "0x00000090",
+ "lane3": "0x00000090",
+ "lane4": "0x00000090",
+ "lane5": "0x00000090",
+ "lane6": "0x0000007C",
+ "lane7": "0x00000088"
+ },
+ "post1": {
+ "lane0": "0xfffffff4",
+ "lane1": "0xfffffff8",
+ "lane2": "0xfffffff4",
+ "lane3": "0xfffffff4",
+ "lane4": "0xfffffff4",
+ "lane5": "0xfffffff4",
+ "lane6": "0xfffffff8",
+ "lane7": "0xfffffff4"
+ },
+ "post2": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ },
+ "post3": {
+ "lane0": "0x00000000",
+ "lane1": "0x00000000",
+ "lane2": "0x00000000",
+ "lane3": "0x00000000",
+ "lane4": "0x00000000",
+ "lane5": "0x00000000",
+ "lane6": "0x00000000",
+ "lane7": "0x00000000"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/monitor.py b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/monitor.py
new file mode 100644
index 000000000000..307b0d0581d9
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/monitor.py
@@ -0,0 +1,402 @@
+#!/usr/bin/python3
+# * onboard temperature sensors
+# * FAN trays
+# * PSU
+#
+import os
+import xml.etree.ElementTree as ET
+import glob
+import json
+from decimal import Decimal
+from fru import ipmifru
+
+
+MAILBOX_DIR = "/sys/bus/i2c/devices/"
+BOARD_ID_PATH = "/sys/module/platform_common/parameters/dfd_my_type"
+BOARD_AIRFLOW_PATH = "/etc/sonic/.airflow"
+
+
+CONFIG_NAME = "dev.xml"
+
+
+def byteTostr(val):
+ strtmp = ''
+ for value in val:
+ strtmp += chr(value)
+ return strtmp
+
+
+def typeTostr(val):
+ if isinstance(val, bytes):
+ strtmp = byteTostr(val)
+ return strtmp
+ return val
+
+
+def get_board_id():
+ if not os.path.exists(BOARD_ID_PATH):
+ return "NA"
+ with open(BOARD_ID_PATH) as fd:
+ id_str = fd.read().strip()
+ return "0x%x" % (int(id_str, 10))
+
+
+def getboardairflow():
+ if not os.path.exists(BOARD_AIRFLOW_PATH):
+ return "NA"
+ with open(BOARD_AIRFLOW_PATH) as fd:
+ airflow_str = fd.read().strip()
+ data = json.loads(airflow_str)
+ airflow = data.get("board", "NA")
+ return airflow
+
+
+boardid = get_board_id()
+boardairflow = getboardairflow()
+
+
+DEV_XML_FILE_LIST = [
+ "dev_" + boardid + "_" + boardairflow + ".xml",
+ "dev_" + boardid + ".xml",
+ "dev_" + boardairflow + ".xml",
+]
+
+
+def dev_file_read(path, offset, read_len):
+ retval = "ERR"
+ val_list = []
+ msg = ""
+ ret = ""
+ fd = -1
+
+ if not os.path.exists(path):
+ return False, "%s %s not found" % (retval, path)
+
+ try:
+ fd = os.open(path, os.O_RDONLY)
+ os.lseek(fd, offset, os.SEEK_SET)
+ ret = os.read(fd, read_len)
+ for item in ret:
+ val_list.append(item)
+ except Exception as e:
+ msg = str(e)
+ return False, "%s %s" % (retval, msg)
+ finally:
+ if fd > 0:
+ os.close(fd)
+ return True, val_list
+
+
+def getPMCreg(location):
+ retval = 'ERR'
+ if not os.path.isfile(location):
+ return "%s %s notfound" % (retval, location)
+ try:
+ with open(location, 'r') as fd:
+ retval = fd.read()
+ except Exception as error:
+ return "ERR %s" % str(error)
+
+ retval = retval.rstrip('\r\n')
+ retval = retval.lstrip(" ")
+ return retval
+
+
+# Get a mailbox register
+def get_pmc_register(reg_name):
+ retval = 'ERR'
+ mb_reg_file = reg_name
+ filepath = glob.glob(mb_reg_file)
+ if len(filepath) == 0:
+ return "%s %s notfound" % (retval, mb_reg_file)
+ mb_reg_file = filepath[0]
+ if not os.path.isfile(mb_reg_file):
+ # print mb_reg_file, 'not found !'
+ return "%s %s notfound" % (retval, mb_reg_file)
+ try:
+ with open(mb_reg_file, 'rb') as fd:
+ retval = fd.read()
+ retval = typeTostr(retval)
+ except Exception as error:
+ retval = "%s %s read failed, msg: %s" % (retval, mb_reg_file, str(error))
+
+ retval = retval.rstrip('\r\n')
+ retval = retval.lstrip(" ")
+ return retval
+
+
+class checktype():
+ def __init__(self, test1):
+ self.test1 = test1
+
+ @staticmethod
+ def getValue(location, bit, data_type, coefficient=1, addend=0):
+ try:
+ value_t = get_pmc_register(location)
+ if value_t.startswith("ERR") or value_t.startswith("NA"):
+ return value_t
+ if data_type == 1:
+ return float('%.1f' % ((float(value_t) / 1000) + addend))
+ if data_type == 2:
+ return float('%.1f' % (float(value_t) / 100))
+ if data_type == 3:
+ psu_status = int(value_t, 16)
+ return (psu_status & (1 << bit)) >> bit
+ if data_type == 4:
+ return int(value_t, 10)
+ if data_type == 5:
+ return float('%.1f' % (float(value_t) / 1000 / 1000))
+ if data_type == 6:
+ return Decimal(float(value_t) * coefficient / 1000).quantize(Decimal('0.000'))
+ return value_t
+ except Exception as e:
+ value_t = "ERR %s" % str(e)
+ return value_t
+
+ # fanFRU
+ @staticmethod
+ def decodeBinByValue(retval):
+ fru = ipmifru()
+ fru.decodeBin(retval)
+ return fru
+
+ @staticmethod
+ def getfruValue(prob_t, root, val):
+ try:
+ ret, binval_bytes = dev_file_read(val, 0, 256)
+ if ret is False:
+ return binval_bytes
+ binval = byteTostr(binval_bytes)
+ fanpro = {}
+ ret = checktype.decodeBinByValue(binval)
+ fanpro['fan_type'] = ret.productInfoArea.productName
+ fanpro['hw_version'] = ret.productInfoArea.productVersion
+ fanpro['sn'] = ret.productInfoArea.productSerialNumber
+ fan_display_name_dict = status.getDecodValue(root, "fan_display_name")
+ fan_name = fanpro['fan_type'].strip()
+ if len(fan_display_name_dict) == 0:
+ return fanpro
+ if fan_name not in fan_display_name_dict:
+ prob_t['errcode'] = -1
+ prob_t['errmsg'] = '%s' % ("ERR fan name: %s not support" % fan_name)
+ else:
+ fanpro['fan_type'] = fan_display_name_dict[fan_name]
+ return fanpro
+ except Exception as error:
+ return "ERR " + str(error)
+
+ @staticmethod
+ def getslotfruValue(val):
+ try:
+ binval = checktype.getValue(val, 0, 0)
+ if binval.startswith("ERR"):
+ return binval
+ slotpro = {}
+ ret = checktype.decodeBinByValue(binval)
+ slotpro['slot_type'] = ret.boardInfoArea.boardProductName
+ slotpro['hw_version'] = ret.boardInfoArea.boardextra1
+ slotpro['sn'] = ret.boardInfoArea.boardSerialNumber
+ return slotpro
+ except Exception as error:
+ return "ERR " + str(error)
+
+ @staticmethod
+ def getpsufruValue(prob_t, root, val):
+ try:
+ psu_match = False
+ binval = checktype.getValue(val, 0, 0)
+ if binval.startswith("ERR"):
+ return binval
+ psupro = {}
+ ret = checktype.decodeBinByValue(binval)
+ psupro['type1'] = ret.productInfoArea.productPartModelName
+ psupro['sn'] = ret.productInfoArea.productSerialNumber
+ psupro['hw_version'] = ret.productInfoArea.productVersion
+ psu_dict = status.getDecodValue(root, "psutype")
+ psupro['type1'] = psupro['type1'].strip()
+ if len(psu_dict) == 0:
+ return psupro
+ for psu_name, display_name in psu_dict.items():
+ if psu_name.strip() == psupro['type1']:
+ psupro['type1'] = display_name
+ psu_match = True
+ break
+ if psu_match is not True:
+ prob_t['errcode'] = -1
+ prob_t['errmsg'] = '%s' % ("ERR psu name: %s not support" % psupro['type1'])
+ return psupro
+ except Exception as error:
+ return "ERR " + str(error)
+
+
+class status():
+ def __init__(self, productname):
+ self.productname = productname
+
+ @staticmethod
+ def getETroot(filename):
+ tree = ET.parse(filename)
+ root = tree.getroot()
+ return root
+
+ @staticmethod
+ def getDecodValue(collection, decode):
+ decodes = collection.find('decode')
+ testdecode = decodes.find(decode)
+ test = {}
+ if testdecode is None:
+ return test
+ for neighbor in testdecode.iter('code'):
+ test[neighbor.attrib["key"]] = neighbor.attrib["value"]
+ return test
+
+ @staticmethod
+ def getfileValue(location):
+ return checktype.getValue(location, " ", " ")
+
+ @staticmethod
+ def getETValue(a, filename, tagname):
+ root = status.getETroot(filename)
+ for neighbor in root.iter(tagname):
+ prob_t = {}
+ prob_t = neighbor.attrib
+ prob_t['errcode'] = 0
+ prob_t['errmsg'] = ''
+ for pros in neighbor.iter("property"):
+ ret = dict(list(neighbor.attrib.items()) + list(pros.attrib.items()))
+ if ret.get('e2type') == 'fru' and ret.get("name") == "fru":
+ fruval = checktype.getfruValue(prob_t, root, ret["location"])
+ if isinstance(fruval, str) and fruval.startswith("ERR"):
+ prob_t['errcode'] = -1
+ prob_t['errmsg'] = fruval
+ break
+ prob_t.update(fruval)
+ continue
+
+ if ret.get("name") == "psu" and ret.get('e2type') == 'fru':
+ psuval = checktype.getpsufruValue(prob_t, root, ret["location"])
+ if isinstance(psuval, str) and psuval.startswith("ERR"):
+ prob_t['errcode'] = -1
+ prob_t['errmsg'] = psuval
+ break
+ prob_t.update(psuval)
+ continue
+
+ if ret.get("gettype") == "config":
+ prob_t[ret["name"]] = ret["value"]
+ continue
+
+ if 'type' not in ret.keys():
+ val = "0"
+ else:
+ val = ret["type"]
+ if 'bit' not in ret.keys():
+ bit = "0"
+ else:
+ bit = ret["bit"]
+ if 'coefficient' not in ret.keys():
+ coefficient = 1
+ else:
+ coefficient = float(ret["coefficient"])
+ if 'addend' not in ret.keys():
+ addend = 0
+ else:
+ addend = float(ret["addend"])
+
+ s = checktype.getValue(ret["location"], int(bit), int(val), coefficient, addend)
+ if isinstance(s, str) and s.startswith("ERR"):
+ prob_t['errcode'] = -1
+ prob_t['errmsg'] = s
+ break
+ if 'default' in ret.keys():
+ rt = status.getDecodValue(root, ret['decode'])
+ prob_t['errmsg'] = rt[str(s)]
+ if str(s) != ret["default"]:
+ prob_t['errcode'] = -1
+ break
+ else:
+ if 'decode' in ret.keys():
+ rt = status.getDecodValue(root, ret['decode'])
+ if (ret['decode'] == "psutype" and s.replace("\x00", "").rstrip() not in rt):
+ prob_t['errcode'] = -1
+ prob_t['errmsg'] = '%s' % ("ERR psu name: %s not support" %
+ (s.replace("\x00", "").rstrip()))
+ else:
+ s = rt[str(s).replace("\x00", "").rstrip()]
+ name = ret["name"]
+ prob_t[name] = str(s)
+ a.append(prob_t)
+
+ @staticmethod
+ def getCPUValue(a, filename, tagname):
+ root = status.getETroot(filename)
+ for neighbor in root.iter(tagname):
+ location = neighbor.attrib["location"]
+ L = []
+ for dirpath, dirnames, filenames in os.walk(location):
+ for file in filenames:
+ if file.endswith("input"):
+ L.append(os.path.join(dirpath, file))
+ L = sorted(L, reverse=False)
+ for i in range(len(L)):
+ prob_t = {}
+ prob_t["name"] = getPMCreg("%s/temp%d_label" % (location, i + 1))
+ prob_t["temp"] = float(getPMCreg("%s/temp%d_input" % (location, i + 1))) / 1000
+ prob_t["alarm"] = float(getPMCreg("%s/temp%d_crit_alarm" % (location, i + 1))) / 1000
+ prob_t["crit"] = float(getPMCreg("%s/temp%d_crit" % (location, i + 1))) / 1000
+ prob_t["max"] = float(getPMCreg("%s/temp%d_max" % (location, i + 1))) / 1000
+ a.append(prob_t)
+
+ @staticmethod
+ def getFileName():
+ fpath = os.path.dirname(os.path.realpath(__file__))
+ for file in DEV_XML_FILE_LIST:
+ xml = fpath + "/" + file
+ if os.path.exists(xml):
+ return xml
+ return fpath + "/" + CONFIG_NAME
+
+ @staticmethod
+ def checkFan(ret):
+ _filename = status.getFileName()
+ # _filename = "/usr/local/bin/" + status.getFileName()
+ _tagname = "fan"
+ status.getETValue(ret, _filename, _tagname)
+
+ @staticmethod
+ def getTemp(ret):
+ _filename = status.getFileName()
+ # _filename = "/usr/local/bin/" + status.getFileName()
+ _tagname = "temp"
+ status.getETValue(ret, _filename, _tagname)
+
+ @staticmethod
+ def getPsu(ret):
+ _filename = status.getFileName()
+ # _filename = "/usr/local/bin/" + status.getFileName()
+ _tagname = "psu"
+ status.getETValue(ret, _filename, _tagname)
+
+ @staticmethod
+ def getcputemp(ret):
+ _filename = status.getFileName()
+ _tagname = "cpus"
+ status.getCPUValue(ret, _filename, _tagname)
+
+ @staticmethod
+ def getDcdc(ret):
+ _filename = status.getFileName()
+ _tagname = "dcdc"
+ status.getETValue(ret, _filename, _tagname)
+
+ @staticmethod
+ def getmactemp(ret):
+ _filename = status.getFileName()
+ _tagname = "mactemp"
+ status.getETValue(ret, _filename, _tagname)
+
+ @staticmethod
+ def getmacpower(ret):
+ _filename = status.getFileName()
+ _tagname = "macpower"
+ status.getETValue(ret, _filename, _tagname)
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/pcie.yaml b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/pcie.yaml
new file mode 100755
index 000000000000..ee025879f7f8
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/pcie.yaml
@@ -0,0 +1,581 @@
+- bus: '00'
+ dev: '00'
+ fn: '0'
+ id: 6f00
+ name: 'Host bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D DMI2
+ (rev 05)'
+- bus: '00'
+ dev: '01'
+ fn: '0'
+ id: 6f02
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 1 (rev 05)'
+- bus: '00'
+ dev: '01'
+ fn: '1'
+ id: 6f03
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 1 (rev 05)'
+- bus: '00'
+ dev: '02'
+ fn: '0'
+ id: 6f04
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 2 (rev 05)'
+- bus: '00'
+ dev: '02'
+ fn: '2'
+ id: 6f06
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 2 (rev 05)'
+- bus: '00'
+ dev: '02'
+ fn: '3'
+ id: 6f07
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 2 (rev 05)'
+- bus: '00'
+ dev: '03'
+ fn: '0'
+ id: 6f08
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 3 (rev 05)'
+- bus: '00'
+ dev: '03'
+ fn: '1'
+ id: 6f09
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 3 (rev 05)'
+- bus: '00'
+ dev: '03'
+ fn: '2'
+ id: 6f0a
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 3 (rev 05)'
+- bus: '00'
+ dev: '03'
+ fn: '3'
+ id: 6f0b
+ name: 'PCI bridge: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D PCI
+ Express Root Port 3 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '0'
+ id: 6f20
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 0 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '1'
+ id: 6f21
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 1 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '2'
+ id: 6f22
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 2 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '3'
+ id: 6f23
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 3 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '4'
+ id: 6f24
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 4 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '5'
+ id: 6f25
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 5 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '6'
+ id: 6f26
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 6 (rev 05)'
+- bus: '00'
+ dev: '04'
+ fn: '7'
+ id: 6f27
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Crystal Beach DMA Channel 7 (rev 05)'
+- bus: '00'
+ dev: '05'
+ fn: '0'
+ id: 6f28
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Map/VTd_Misc/System Management (rev 05)'
+- bus: '00'
+ dev: '05'
+ fn: '1'
+ id: 6f29
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Hot Plug (rev 05)'
+- bus: '00'
+ dev: '05'
+ fn: '2'
+ id: 6f2a
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO RAS/Control Status/Global Errors (rev 05)'
+- bus: '00'
+ dev: '05'
+ fn: '4'
+ id: 6f2c
+ name: 'PIC: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D I/O APIC (rev
+ 05)'
+- bus: '00'
+ dev: '05'
+ fn: '6'
+ id: 6f39
+ name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IO Performance Monitoring (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '0'
+ id: 6f10
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '1'
+ id: 6f11
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '2'
+ id: 6f12
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '3'
+ id: 6f13
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '4'
+ id: 6f14
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '5'
+ id: 6f15
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '6'
+ id: 6f16
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '06'
+ fn: '7'
+ id: 6f17
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '07'
+ fn: '0'
+ id: 6f18
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '07'
+ fn: '1'
+ id: 6f19
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '07'
+ fn: '2'
+ id: 6f1a
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '07'
+ fn: '3'
+ id: 6f1b
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '07'
+ fn: '4'
+ id: 6f1c
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D IIO Debug (rev 05)'
+- bus: '00'
+ dev: '14'
+ fn: '0'
+ id: 8c31
+ name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB
+ xHCI (rev 05)'
+- bus: '00'
+ dev: '16'
+ fn: '0'
+ id: 8c3a
+ name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset
+ Family MEI Controller #1 (rev 04)'
+- bus: '00'
+ dev: '16'
+ fn: '1'
+ id: 8c3b
+ name: 'Communication controller: Intel Corporation 8 Series/C220 Series Chipset
+ Family MEI Controller #2 (rev 04)'
+- bus: '00'
+ dev: 1d
+ fn: '0'
+ id: 8c26
+ name: 'USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB
+ EHCI #1 (rev 05)'
+- bus: '00'
+ dev: 1f
+ fn: '0'
+ id: 8c54
+ name: 'ISA bridge: Intel Corporation C224 Series Chipset Family Server Standard
+ SKU LPC Controller (rev 05)'
+- bus: '00'
+ dev: 1f
+ fn: '2'
+ id: 8c02
+ name: 'SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port
+ SATA Controller 1 [AHCI mode] (rev 05)'
+- bus: '00'
+ dev: 1f
+ fn: '3'
+ id: 8c22
+ name: 'SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller
+ (rev 05)'
+- bus: '04'
+ dev: '00'
+ fn: '0'
+ id: 15ab
+ name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane'
+- bus: '04'
+ dev: '00'
+ fn: '1'
+ id: 15ab
+ name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane'
+- bus: '05'
+ dev: '00'
+ fn: '0'
+ id: 15ab
+ name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane'
+- bus: '05'
+ dev: '00'
+ fn: '1'
+ id: 15ab
+ name: 'Ethernet controller: Intel Corporation Ethernet Connection X552 10 GbE Backplane'
+- bus: '06'
+ dev: '00'
+ fn: '0'
+ id: b780
+ name: 'Ethernet controller: Broadcom Inc. and subsidiaries Device b780 (rev 01)'
+- bus: '07'
+ dev: '00'
+ fn: '0'
+ id: '1537'
+ name: 'Ethernet controller: Intel Corporation I210 Gigabit Backplane Connection
+ (rev 03)'
+- bus: 08
+ dev: '00'
+ fn: '0'
+ id: '7011'
+ name: 'Memory controller: Xilinx Corporation Device 7011'
+- bus: ff
+ dev: 0b
+ fn: '0'
+ id: 6f81
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D R3 QPI Link 0/1 (rev 05)'
+- bus: ff
+ dev: 0b
+ fn: '1'
+ id: 6f36
+ name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D R3 QPI Link 0/1 (rev 05)'
+- bus: ff
+ dev: 0b
+ fn: '2'
+ id: 6f37
+ name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D R3 QPI Link 0/1 (rev 05)'
+- bus: ff
+ dev: 0b
+ fn: '3'
+ id: 6f76
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D R3 QPI Link Debug (rev 05)'
+- bus: ff
+ dev: 0c
+ fn: '0'
+ id: 6fe0
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: 0c
+ fn: '1'
+ id: 6fe1
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: 0c
+ fn: '2'
+ id: 6fe2
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: 0c
+ fn: '3'
+ id: 6fe3
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: 0f
+ fn: '0'
+ id: 6ff8
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: 0f
+ fn: '4'
+ id: 6ffc
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: 0f
+ fn: '5'
+ id: 6ffd
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: 0f
+ fn: '6'
+ id: 6ffe
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Caching Agent (rev 05)'
+- bus: ff
+ dev: '10'
+ fn: '0'
+ id: 6f1d
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D R2PCIe Agent (rev 05)'
+- bus: ff
+ dev: '10'
+ fn: '1'
+ id: 6f34
+ name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D R2PCIe Agent (rev 05)'
+- bus: ff
+ dev: '10'
+ fn: '5'
+ id: 6f1e
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Ubox (rev 05)'
+- bus: ff
+ dev: '10'
+ fn: '6'
+ id: 6f7d
+ name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Ubox (rev 05)'
+- bus: ff
+ dev: '10'
+ fn: '7'
+ id: 6f1f
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Ubox (rev 05)'
+- bus: ff
+ dev: '12'
+ fn: '0'
+ id: 6fa0
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Home Agent 0 (rev 05)'
+- bus: ff
+ dev: '12'
+ fn: '1'
+ id: 6f30
+ name: 'Performance counters: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Home Agent 0 (rev 05)'
+- bus: ff
+ dev: '12'
+ fn: '2'
+ id: 6f70
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Home Agent 0 Debug (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '0'
+ id: 6fa8
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Target Address/Thermal/RAS (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '1'
+ id: 6f71
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Target Address/Thermal/RAS (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '2'
+ id: 6faa
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel Target Address Decoder (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '3'
+ id: 6fab
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel Target Address Decoder (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '4'
+ id: 6fac
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel Target Address Decoder (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '5'
+ id: 6fad
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel Target Address Decoder (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '6'
+ id: 6fae
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D DDRIO Channel 0/1 Broadcast (rev 05)'
+- bus: ff
+ dev: '13'
+ fn: '7'
+ id: 6faf
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D DDRIO Global Broadcast (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '0'
+ id: 6fb0
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 0 Thermal Control (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '1'
+ id: 6fb1
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 1 Thermal Control (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '2'
+ id: 6fb2
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 0 Error (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '3'
+ id: 6fb3
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 1 Error (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '4'
+ id: 6fbc
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D DDRIO Channel 0/1 Interface (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '5'
+ id: 6fbd
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D DDRIO Channel 0/1 Interface (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '6'
+ id: 6fbe
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D DDRIO Channel 0/1 Interface (rev 05)'
+- bus: ff
+ dev: '14'
+ fn: '7'
+ id: 6fbf
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D DDRIO Channel 0/1 Interface (rev 05)'
+- bus: ff
+ dev: '15'
+ fn: '0'
+ id: 6fb4
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 2 Thermal Control (rev 05)'
+- bus: ff
+ dev: '15'
+ fn: '1'
+ id: 6fb5
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 3 Thermal Control (rev 05)'
+- bus: ff
+ dev: '15'
+ fn: '2'
+ id: 6fb6
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 2 Error (rev 05)'
+- bus: ff
+ dev: '15'
+ fn: '3'
+ id: 6fb7
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Memory Controller 0 - Channel 3 Error (rev 05)'
+- bus: ff
+ dev: 1e
+ fn: '0'
+ id: 6f98
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Power Control Unit (rev 05)'
+- bus: ff
+ dev: 1e
+ fn: '1'
+ id: 6f99
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Power Control Unit (rev 05)'
+- bus: ff
+ dev: 1e
+ fn: '2'
+ id: 6f9a
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Power Control Unit (rev 05)'
+- bus: ff
+ dev: 1e
+ fn: '3'
+ id: 6fc0
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Power Control Unit (rev 05)'
+- bus: ff
+ dev: 1e
+ fn: '4'
+ id: 6f9c
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Power Control Unit (rev 05)'
+- bus: ff
+ dev: 1e
+ fn: '7'
+ id: 6f9f
+ name: 'System peripheral: Intel Corporation Device 6f9f (rev 05)'
+- bus: ff
+ dev: 1f
+ fn: '0'
+ id: 6f88
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Power Control Unit (rev 05)'
+- bus: ff
+ dev: 1f
+ fn: '2'
+ id: 6f8a
+ name: 'System peripheral: Intel Corporation Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon
+ D Power Control Unit (rev 05)'
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform.json
new file mode 100644
index 000000000000..1af747fd7317
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform.json
@@ -0,0 +1,737 @@
+{
+ "chassis": {
+ "name": "M2-W6520-24DC8QC",
+ "thermal_manager": false,
+ "status_led": {
+ "controllable": false,
+ "colors": ["green", "blinking_green", "amber", "blinking_amber"]
+ },
+ "components": [
+ {
+ "name": "CPU_CPLD"
+ },
+ {
+ "name": "CONNECT_CPLD"
+ },
+ {
+ "name": "MAC_CPLDA"
+ },
+ {
+ "name": "MAC_CPLDB"
+ },
+ {
+ "name": "FAN_CPLD"
+ },
+ {
+ "name": "FPGA"
+ },
+ {
+ "name": "BIOS"
+ }
+ ],
+ "fans": [
+ {
+ "name": "Fantray1_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray1_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray2_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray2_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray3_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray3_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray4_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray4_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray5_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray5_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray6_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ },
+ {
+ "name": "Fantray6_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false,
+ "colors": ["off", "red", "amber", "green"]
+ }
+ }
+ ],
+ "fan_drawers":[
+ {
+ "name": "Fantray1",
+ "num_fans" : 2,
+ "status_led": {
+ "controllable": false,
+ "colors": ["amber", "green", "off"]
+ },
+ "fans": [
+ {
+ "name": "Fantray1_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ },
+ {
+ "name": "Fantray1_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ },
+ {
+ "name": "Fantray2",
+ "num_fans" : 2,
+ "status_led": {
+ "controllable": false,
+ "colors": ["amber", "green", "off"]
+ },
+ "fans": [
+ {
+ "name": "Fantray2_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ },
+ {
+ "name": "Fantray2_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ },
+ {
+ "name": "Fantray3",
+ "num_fans" : 2,
+ "status_led": {
+ "controllable": false,
+ "colors": ["amber", "green", "off"]
+ },
+ "fans": [
+ {
+ "name": "Fantray3_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ },
+ {
+ "name": "Fantray3_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ },
+ {
+ "name": "Fantray4",
+ "num_fans" : 2,
+ "status_led": {
+ "controllable": false,
+ "colors": ["amber", "green", "off"]
+ },
+ "fans": [
+ {
+ "name": "Fantray4_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ },
+ {
+ "name": "Fantray4_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ },
+ {
+ "name": "Fantray5",
+ "num_fans" : 2,
+ "status_led": {
+ "controllable": false,
+ "colors": ["amber", "green", "off"]
+ },
+ "fans": [
+ {
+ "name": "Fantray5_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ },
+ {
+ "name": "Fantray5_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ },
+ {
+ "name": "Fantray6",
+ "num_fans" : 2,
+ "status_led": {
+ "controllable": false,
+ "colors": ["amber", "green", "off"]
+ },
+ "fans": [
+ {
+ "name": "Fantray6_1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ },
+ {
+ "name": "Fantray6_2",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ }
+ ],
+ "psus": [
+ {
+ "name": "Psu1",
+ "voltage": true,
+ "current": true,
+ "power": true,
+ "max_power": false,
+ "voltage_high_threshold": true,
+ "voltage_low_threshold": true,
+ "temperature": true,
+ "fans_target_speed": true,
+ "status_led": {
+ "controllable": false
+ },
+ "fans": [
+ {
+ "name": "PSU1_FAN1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ },
+ {
+ "name": "Psu2",
+ "voltage": true,
+ "current": true,
+ "power": true,
+ "max_power": false,
+ "voltage_high_threshold": true,
+ "voltage_low_threshold": true,
+ "temperature": true,
+ "fans_target_speed": true,
+ "status_led": {
+ "controllable": false
+ },
+ "fans": [
+ {
+ "name": "PSU2_FAN1",
+ "speed": {
+ "controllable": true,
+ "minimum": 50,
+ "maximum": 100
+ },
+ "status_led": {
+ "available": false
+ }
+ }
+ ]
+ }
+ ],
+ "thermals": [
+ {
+ "name": "BOARD_TEMP",
+ "controllable": false,
+ "low-crit-threshold": true,
+ "high-crit-threshold": true,
+ "low-threshold": true,
+ "high-threshold": true,
+ "minimum-recorded": true,
+ "maximum-recorded": true
+ },
+ {
+ "name": "CPU_TEMP",
+ "controllable": false,
+ "low-crit-threshold": true,
+ "high-crit-threshold": true,
+ "low-threshold": true,
+ "high-threshold": true,
+ "minimum-recorded": true,
+ "maximum-recorded": true
+ },
+ {
+ "name": "INLET_TEMP",
+ "controllable": false,
+ "low-crit-threshold": true,
+ "high-crit-threshold": true,
+ "low-threshold": true,
+ "high-threshold": true,
+ "minimum-recorded": true,
+ "maximum-recorded": true
+ },
+ {
+ "name": "OUTLET_TEMP",
+ "controllable": false,
+ "low-crit-threshold": true,
+ "high-crit-threshold": true,
+ "low-threshold": true,
+ "high-threshold": true,
+ "minimum-recorded": true,
+ "maximum-recorded": true
+ },
+ {
+ "name": "ASIC_TEMP",
+ "controllable": false,
+ "low-crit-threshold": true,
+ "high-crit-threshold": true,
+ "low-threshold": true,
+ "high-threshold": true,
+ "minimum-recorded": true,
+ "maximum-recorded": true
+ },
+ {
+ "name": "PSU1_TEMP",
+ "controllable": false,
+ "low-crit-threshold": true,
+ "high-crit-threshold": true,
+ "low-threshold": true,
+ "high-threshold": true,
+ "minimum-recorded": true,
+ "maximum-recorded": true
+ },
+ {
+ "name": "PSU2_TEMP",
+ "controllable": false,
+ "low-crit-threshold": true,
+ "high-crit-threshold": true,
+ "low-threshold": true,
+ "high-threshold": true,
+ "minimum-recorded": true,
+ "maximum-recorded": true
+ }
+ ],
+ "modules": [],
+ "sfps": []
+ },
+ "interfaces": {
+ "Ethernet1": {
+ "index": "0,0,0,0",
+ "lanes": "25,26,27,28",
+ "breakout_modes": {
+ "1x200G": ["Eth1"]
+ }
+ },
+ "Ethernet2": {
+ "index": "1,1,1,1",
+ "lanes": "29,30,31,32",
+ "breakout_modes": {
+ "1x200G": ["Eth2"]
+ }
+ },
+ "Ethernet3": {
+ "index": "2,2,2,2",
+ "lanes": "41,42,43,44",
+ "breakout_modes": {
+ "1x200G": ["Eth3"]
+ }
+ },
+ "Ethernet4": {
+ "index": "3,3,3,3",
+ "lanes": "45,46,47,48",
+ "breakout_modes": {
+ "1x200G": ["Eth4"]
+ }
+ },
+ "Ethernet5": {
+ "index": "4,4,4,4",
+ "lanes": "49,50,51,52",
+ "breakout_modes": {
+ "1x200G": ["Eth5"]
+ }
+ },
+ "Ethernet6": {
+ "index": "5,5,5,5",
+ "lanes": "53,54,55,56",
+ "breakout_modes": {
+ "1x200G": ["Eth6"]
+ }
+ },
+ "Ethernet7": {
+ "index": "6,6,6,6",
+ "lanes": "57,58,59,60",
+ "breakout_modes": {
+ "1x200G": ["Eth7"]
+ }
+ },
+ "Ethernet8": {
+ "index": "7,7,7,7",
+ "lanes": "61,62,63,64",
+ "breakout_modes": {
+ "1x200G": ["Eth8"]
+ }
+ },
+ "Ethernet9": {
+ "index": "8,8,8,8",
+ "lanes": "9,10,11,12",
+ "breakout_modes": {
+ "1x200G": ["Eth9"]
+ }
+ },
+ "Ethernet10": {
+ "index": "9,9,9,9",
+ "lanes": "13,14,15,16",
+ "breakout_modes": {
+ "1x200G": ["Eth10"]
+ }
+ },
+ "Ethernet11": {
+ "index": "10,10,10,10",
+ "lanes": "17,18,19,20",
+ "breakout_modes": {
+ "1x200G": ["Eth11"]
+ }
+ },
+ "Ethernet12": {
+ "index": "11,11,11,11",
+ "lanes": "21,22,23,24",
+ "breakout_modes": {
+ "1x200G": ["Eth12"]
+ }
+ },
+ "Ethernet13": {
+ "index": "12,12,12,12",
+ "lanes": "81,82,83,84",
+ "breakout_modes": {
+ "1x200G": ["Eth13"]
+ }
+ },
+ "Ethernet14": {
+ "index": "13,13,13,13",
+ "lanes": "85,86,87,88",
+ "breakout_modes": {
+ "1x200G": ["Eth14"]
+ }
+ },
+ "Ethernet15": {
+ "index": "14,14,14,14",
+ "lanes": "89,90,91,92",
+ "breakout_modes": {
+ "1x200G": ["Eth15"]
+ }
+ },
+ "Ethernet16": {
+ "index": "15,15,15,15",
+ "lanes": "93,94,95,96",
+ "breakout_modes": {
+ "1x200G": ["Eth16"]
+ }
+ },
+ "Ethernet17": {
+ "index": "16,16,16,16",
+ "lanes": "97,98,99,100",
+ "breakout_modes": {
+ "1x200G": ["Eth17"]
+ }
+ },
+ "Ethernet18": {
+ "index": "17,17,17,17",
+ "lanes": "101,102,103,104",
+ "breakout_modes": {
+ "1x200G": ["Eth18"]
+ }
+ },
+ "Ethernet19": {
+ "index": "18,18,18,18",
+ "lanes": "137,138,139,140",
+ "breakout_modes": {
+ "1x200G": ["Eth19"]
+ }
+ },
+ "Ethernet20": {
+ "index": "19,19,19,19",
+ "lanes": "141,142,143,144",
+ "breakout_modes": {
+ "1x200G": ["Eth20"]
+ }
+ },
+ "Ethernet21": {
+ "index": "20,20,20,20",
+ "lanes": "145,146,147,148",
+ "breakout_modes": {
+ "1x200G": ["Eth21"]
+ }
+ },
+ "Ethernet22": {
+ "index": "21,21,21,21",
+ "lanes": "149,150,151,152",
+ "breakout_modes": {
+ "1x200G": ["Eth22"]
+ }
+ },
+ "Ethernet23": {
+ "index": "22,22,22,22",
+ "lanes": "153,154,155,156",
+ "breakout_modes": {
+ "1x200G": ["Eth23"]
+ }
+ },
+ "Ethernet24": {
+ "index": "23,23,23,23",
+ "lanes": "157,158,159,160",
+ "breakout_modes": {
+ "1x200G": ["Eth24"]
+ }
+ },
+ "Ethernet25": {
+ "index": "24,24,24,24,24,24,24,24",
+ "lanes": "1,2,3,4,5,6,7,8",
+ "breakout_modes": {
+ "1x400G": ["Eth25"],
+ "2x200G[100G]": ["Eth25/1", "Eth25/2"]
+ }
+ },
+ "Ethernet33": {
+ "index": "25,25,25,25,25,25,25,25",
+ "lanes": "33,34,35,36,37,38,39,40",
+ "breakout_modes": {
+ "1x400G": ["Eth26"],
+ "2x200G[100G]": ["Eth26/1", "Eth26/2"]
+ }
+ },
+ "Ethernet41": {
+ "index": "26,26,26,26,26,26,26,26",
+ "lanes": "65,66,67,68,69,70,71,72",
+ "breakout_modes": {
+ "1x400G": ["Eth27"],
+ "2x200G[100G]": ["Eth27/1", "Eth27/2"]
+ }
+ },
+ "Ethernet49": {
+ "index": "27,27,27,27,27,27,27,27",
+ "lanes": "73,74,75,76,77,78,79,80",
+ "breakout_modes": {
+ "1x400G": ["Eth28"],
+ "2x200G[100G]": ["Eth28/1", "Eth28/2"]
+ }
+ },
+ "Ethernet57": {
+ "index": "28,28,28,28,28,28,28,28",
+ "lanes": "105,106,107,108,109,110,111,112",
+ "breakout_modes": {
+ "1x400G": ["Eth29"],
+ "2x200G[100G]": ["Eth29/1", "Eth29/2"]
+ }
+ },
+ "Ethernet65": {
+ "index": "29,29,29,29,29,29,29,29",
+ "lanes": "113,114,115,116,117,118,119,120",
+ "breakout_modes": {
+ "1x400G": ["Eth30"],
+ "2x200G[100G]": ["Eth30/1", "Eth30/2"]
+ }
+ },
+ "Ethernet73": {
+ "index": "30,30,30,30,30,30,30,30",
+ "lanes": "121,122,123,124,125,126,127,128",
+ "breakout_modes": {
+ "1x400G": ["Eth31"],
+ "2x200G[100G]": ["Eth31/1", "Eth31/2"]
+ }
+ },
+ "Ethernet81": {
+ "index": "31,31,31,31,31,31,31,31",
+ "lanes": "129,130,131,132,133,134,135,136",
+ "breakout_modes": {
+ "1x400G": ["Eth32"],
+ "2x200G[100G]": ["Eth32/1", "Eth32/2"]
+ }
+ }
+ }
+}
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_asic b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_asic
new file mode 100644
index 000000000000..960467652765
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_asic
@@ -0,0 +1 @@
+broadcom
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_components.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_components.json
new file mode 100644
index 000000000000..8fc136f7b9b1
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_components.json
@@ -0,0 +1,16 @@
+{
+ "chassis": {
+ "M2-W6520-24DC8QC": {
+ "component": {
+ "CPU_CPLD": { },
+ "CONNECT_CPLD": { },
+ "FAN_CPLD": { },
+ "MAC_CPLDA": { },
+ "MAC_CPLDB": { },
+ "FPGA": { },
+ "BIOS": { }
+ }
+ }
+ }
+}
+
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_env.conf b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_env.conf
new file mode 100644
index 000000000000..fc119184d5c1
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform_env.conf
@@ -0,0 +1,2 @@
+is_ltsw_chip=1
+SYNCD_SHM_SIZE=1g
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/plugins/sfputil.py b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/plugins/sfputil.py
new file mode 100644
index 000000000000..f6c4e0477c57
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/plugins/sfputil.py
@@ -0,0 +1,365 @@
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+
+try:
+ import time
+ import re
+ import os
+ import threading
+ import traceback
+ import subprocess
+ from ctypes import create_string_buffer
+ from sonic_sfp.sfputilbase import SfpUtilBase
+ from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom
+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 = 31
+ PORTS_IN_BLOCK = 32
+
+ EEPROM_OFFSET = 46
+ SFP_DEVICE_TYPE = "optoe2"
+ QSFP_DEVICE_TYPE = "optoe1"
+ QSFP_DD_DEVICE_TYPE = "optoe3"
+ I2C_MAX_ATTEMPT = 3
+
+ OPTOE_TYPE1 = 1
+ OPTOE_TYPE2 = 2
+ OPTOE_TYPE3 = 3
+
+ SFP_STATUS_INSERTED = '1'
+ SFP_STATUS_REMOVED = '0'
+
+ _port_to_eeprom_mapping = {}
+ port_to_i2cbus_mapping ={}
+ port_dict = {}
+
+ qsfp_ports_list = []
+ qsfp_dd_ports_list = []
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return self.qsfp_ports_list
+
+ @property
+ def qsfp_dd_ports(self):
+ return self.qsfp_dd_ports_list
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
+ self.qsfp_ports_list = []
+ self.qsfp_dd_ports_list = []
+ for x in range(self.PORT_START, self.PORTS_IN_BLOCK):
+ self.port_to_i2cbus_mapping[x] = (x + self.EEPROM_OFFSET)
+
+ if self.get_presence(x):
+ self.port_dict[x] = self.SFP_STATUS_INSERTED
+ else:
+ self.port_dict[x] = self.SFP_STATUS_REMOVED
+
+ if (self.check_is_qsfpdd(x)):
+ self.qsfp_dd_ports_list.append(x)
+ self.check_optoe_type(x, self.OPTOE_TYPE3)
+ else:
+ self.qsfp_ports_list.append(x)
+ self.check_optoe_type(x, self.OPTOE_TYPE1)
+ SfpUtilBase.__init__(self)
+
+ def _sfp_read_file_path(self, file_path, offset, num_bytes):
+ attempts = 0
+ while attempts < self.I2C_MAX_ATTEMPT:
+ try:
+ file_path.seek(offset)
+ read_buf = file_path.read(num_bytes)
+ except:
+ attempts += 1
+ time.sleep(0.05)
+ else:
+ return True, read_buf
+ return False, None
+
+ def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset):
+ """Tries to read the eeprom file to determine if the
+ device/sfp is present or not. If sfp present, the read returns
+ valid bytes. If not, read returns error 'Connection timed out"""
+
+ if not os.path.exists(sysfs_sfp_i2c_client_eeprompath):
+ return False
+ else:
+ with open(sysfs_sfp_i2c_client_eeprompath, "rb", buffering=0) as sysfsfile:
+ rv, buf = self._sfp_read_file_path(sysfsfile, offset, 1)
+ return rv
+
+ def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr, devtype):
+ try:
+ sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path
+
+ # Write device address to new_device file
+ nd_file = open(sysfs_nd_path, "w")
+ nd_str = "%s %s" % (devtype, hex(devaddr))
+ nd_file.write(nd_str)
+ nd_file.close()
+
+ except Exception as err:
+ print("Error writing to new device file: %s" % str(err))
+ return 1
+ else:
+ return 0
+
+ def _get_port_eeprom_path(self, port_num, devid):
+ sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter"
+
+ if port_num in self.port_to_eeprom_mapping.keys():
+ sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num]
+ else:
+ sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter"
+
+ i2c_adapter_id = self._get_port_i2c_adapter_id(port_num)
+ if i2c_adapter_id is None:
+ print("Error getting i2c bus num")
+ return None
+
+ # Get i2c virtual bus path for the sfp
+ sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path,
+ str(i2c_adapter_id))
+
+ # If i2c bus for port does not exist
+ if not os.path.exists(sysfs_sfp_i2c_adapter_path):
+ print("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path)
+ return None
+
+ sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path,
+ str(i2c_adapter_id),
+ hex(devid)[-2:])
+
+ # If sfp device is not present on bus, Add it
+ if not os.path.exists(sysfs_sfp_i2c_client_path):
+ if port_num in self.qsfp_dd_ports:
+ ret = self._add_new_sfp_device(
+ sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DD_DEVICE_TYPE)
+ elif port_num in self.qsfp_ports:
+ ret = self._add_new_sfp_device(
+ sysfs_sfp_i2c_adapter_path, devid, self.QSFP_DEVICE_TYPE)
+ else:
+ ret = self._add_new_sfp_device(
+ sysfs_sfp_i2c_adapter_path, devid, self.SFP_DEVICE_TYPE)
+ if ret != 0:
+ print("Error adding sfp device")
+ return None
+
+ sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path
+
+ return sysfs_sfp_i2c_client_eeprom_path
+
+ def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes):
+ eeprom_raw = []
+ for i in range(0, num_bytes):
+ eeprom_raw.append("0x00")
+
+ rv, raw = self._sfp_read_file_path(sysfsfile_eeprom, offset, num_bytes)
+ if rv == False:
+ return None
+
+ try:
+ for n in range(0, num_bytes):
+ eeprom_raw[n] = hex(raw[n])[2:].zfill(2)
+ except:
+ return None
+
+ return eeprom_raw
+
+ def get_eeprom_dom_raw(self, port_num):
+ if port_num in self.qsfp_ports:
+ # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw
+ return None
+ else:
+ # Read dom eeprom at addr 0x51
+ return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 256)
+
+ 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
+
+ cmd = "cat /sys/wb_plat/sff/sff{}/present".format(str(port_num+1))
+ ret, output = subprocess.getstatusoutput(cmd)
+ if ret != 0:
+ return False
+ if output == "1":
+ return True
+ return False
+
+ def check_is_qsfpdd(self, port_num):
+ try:
+ if self.get_presence(port_num) == False:
+ return False
+
+ eeprom_path = self._get_port_eeprom_path(port_num, 0x50)
+ with open(eeprom_path, mode="rb", buffering=0) as eeprom:
+ eeprom_raw = self._read_eeprom_specific_bytes(eeprom, 0, 1)
+ # according to sff-8024 A0h Byte 0 is '1e' or '18' means the transceiver is qsfpdd
+ if (eeprom_raw[0] == '1e' or eeprom_raw[0] == '18'):
+ return True
+ except Exception as e:
+ print(traceback.format_exc())
+
+ return False
+
+ def check_optoe_type(self, port_num, optoe_type):
+ if self.get_presence(port_num) == False:
+ return True
+ try:
+ eeprom_path = self._get_port_eeprom_path(port_num, 0x50)
+ dev_class_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/dev_class'
+ i2c_path = dev_class_path.format(str(self.port_to_i2cbus_mapping[port_num]))
+ cmd = "cat " + i2c_path
+ ret, output = subprocess.getstatusoutput(cmd)
+ if ret != 0:
+ print("cmd: %s execution fail, output:%s" % (cmd, output))
+ return False
+ if int(output) != optoe_type:
+ cmd = "echo " + str(optoe_type) + " > " + i2c_path
+ ret, output = subprocess.getstatusoutput(cmd)
+ if ret != 0:
+ print("cmd: %s execution fail, output:%s" % (cmd, output))
+ return False
+ return True
+
+ except Exception as e:
+ print(traceback.format_exc())
+ return False
+
+ def get_low_power_mode(self, port_num):
+ # Check for invalid port_num
+
+ return True
+
+ def set_low_power_mode(self, port_num, lpmode):
+ # Check for invalid port_num
+
+ return True
+
+ def reset(self, port_num):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ return True
+
+ def get_transceiver_change_event(self, timeout=0):
+
+ start_time = time.time()
+ current_port_dict = {}
+ forever = False
+
+ if timeout == 0:
+ forever = True
+ elif timeout > 0:
+ timeout = timeout / float(1000) # Convert to secs
+ else:
+ print ("get_transceiver_change_event:Invalid timeout value", timeout)
+ return False, {}
+
+ end_time = start_time + timeout
+ if start_time > end_time:
+ print ('get_transceiver_change_event:' \
+ 'time wrap / invalid timeout value', timeout)
+
+ return False, {} # Time wrap or possibly incorrect timeout
+
+ while timeout >= 0:
+ # Check for OIR events and return updated port_dict
+ for x in range(self.PORT_START, self.PORTS_IN_BLOCK):
+ if self.get_presence(x):
+ current_port_dict[x] = self.SFP_STATUS_INSERTED
+ else:
+ current_port_dict[x] = self.SFP_STATUS_REMOVED
+ if (current_port_dict == self.port_dict):
+ if forever:
+ time.sleep(1)
+ else:
+ timeout = end_time - time.time()
+ if timeout >= 1:
+ time.sleep(1) # We poll at 1 second granularity
+ else:
+ if timeout > 0:
+ time.sleep(timeout)
+ return True, {}
+ else:
+ # Update reg value
+ self.port_dict = current_port_dict
+ return True, self.port_dict
+ print ("get_transceiver_change_event: Should not reach here.")
+ return False, {}
+
+ def get_highest_temperature(self):
+ offset = 0
+ hightest_temperature = -9999
+
+ presence_flag = False
+ read_eeprom_flag = False
+ temperature_valid_flag = False
+
+ for port in range(self.PORT_START, self.PORTS_IN_BLOCK):
+ if self.get_presence(port) == False:
+ continue
+
+ presence_flag = True
+
+ if port in self.qsfp_dd_ports:
+ offset = 14
+ elif port in self.qsfp_ports:
+ offset = 22
+ else:
+ offset = 96
+
+ eeprom_path = self._get_port_eeprom_path(port, 0x50)
+ try:
+ with open(eeprom_path, mode="rb", buffering=0) as eeprom:
+ read_eeprom_flag = True
+ eeprom_raw = self._read_eeprom_specific_bytes(eeprom, offset, 2)
+ if len(eeprom_raw) != 0:
+ msb = int(eeprom_raw[0], 16)
+ lsb = int(eeprom_raw[1], 16)
+
+ result = (msb << 8) | (lsb & 0xff)
+ result = float(result / 256.0)
+ if -50 <= result <= 200:
+ temperature_valid_flag = True
+ if hightest_temperature < result:
+ hightest_temperature = result
+ except Exception as e:
+ pass
+
+ # all port not presence
+ if presence_flag == False:
+ hightest_temperature = -10000
+
+ # all port read eeprom fail
+ elif read_eeprom_flag == False:
+ hightest_temperature = -9999
+
+ # all port temperature invalid
+ elif read_eeprom_flag == True and temperature_valid_flag == False:
+ hightest_temperature = -10000
+
+ hightest_temperature = round(hightest_temperature, 2)
+
+ return hightest_temperature
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/plugins/ssd_util.py b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/plugins/ssd_util.py
new file mode 100644
index 000000000000..932867b34ff7
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/plugins/ssd_util.py
@@ -0,0 +1,318 @@
+#
+# ssd_util.py
+#
+# Generic implementation of the SSD health API
+# SSD models supported:
+# - InnoDisk
+# - StorFly
+# - Virtium
+
+try:
+ import re
+ import os
+ import subprocess
+ from sonic_platform_base.sonic_ssd.ssd_base import SsdBase
+except ImportError as e:
+ raise ImportError (str(e) + "- required module not found")
+
+SMARTCTL = "smartctl {} -a"
+INNODISK = "iSmart -d {}"
+VIRTIUM = "SmartCmd -m {}"
+DISK_LIST_CMD = "fdisk -l -o Device"
+DISK_FREE_CMD = "df -h"
+MOUNT_CMD = "mount"
+
+NOT_AVAILABLE = "N/A"
+PE_CYCLE = 3000
+FAIL_PERCENT = 95
+
+# Set Vendor Specific IDs
+INNODISK_HEALTH_ID = 169
+INNODISK_TEMPERATURE_ID = 194
+
+class SsdUtil(SsdBase):
+ """
+ Generic implementation of the SSD health API
+ """
+ model = NOT_AVAILABLE
+ serial = NOT_AVAILABLE
+ firmware = NOT_AVAILABLE
+ temperature = NOT_AVAILABLE
+ health = NOT_AVAILABLE
+ remaining_life = NOT_AVAILABLE
+ sata_rate = NOT_AVAILABLE
+ ssd_info = NOT_AVAILABLE
+ vendor_ssd_info = NOT_AVAILABLE
+
+ def __init__(self, diskdev):
+ self.vendor_ssd_utility = {
+ "Generic" : { "utility" : SMARTCTL, "parser" : self.parse_generic_ssd_info },
+ "InnoDisk" : { "utility" : INNODISK, "parser" : self.parse_innodisk_info },
+ "M.2" : { "utility" : INNODISK, "parser" : self.parse_innodisk_info },
+ "StorFly" : { "utility" : VIRTIUM, "parser" : self.parse_virtium_info },
+ "Virtium" : { "utility" : VIRTIUM, "parser" : self.parse_virtium_info }
+ }
+
+ """
+ The dict model_attr keys relate the vendors
+ LITEON : "ER2-GD","AF2MA31DTDLT"
+ Intel : "SSDSCKKB"
+ SMI : "SM619GXC"
+ samsung: "MZNLH"
+ ADATA : "IM2S3134N"
+ """
+ self.model_attr = {
+ "ER2-GD" : { "temperature" : "\n190\s+(.+?)\n", "remainingLife" : "\n202\s+(.+?)\n" },
+ "AF2MA31DTDLT" : { "temperature" : "\n194\s+(.+?)\n", "remainingLife" : "\n202\s+(.+?)\n" },
+ "SSDSCK" : { "temperature" : "\n194\s+(.+?)\n", "remainingLife" : "\n233\s+(.+?)\n" },
+ "SM619GXC" : { "temperature" : "\n194\s+(.+?)\n", "remainingLife" : "\n169\s+(.+?)\n" },
+ "MZNLH" : { "temperature" : "\n190\s+(.+?)\n", "remainingLife" : "\n245\s+(.+?)\n" },
+ "IM2S3134N" : { "temperature" : "\n194\s+(.+?)\n", "remainingLife" : "\n231\s+(.+?)\n" },
+ "MTFDDAV240TCB-1AR1ZABAA" : { "temperature" : "\n194\s+(.+?)\n", "remainingLife" : "\n202\s+(.+?)\n" }
+ }
+
+ self.key_list = list(self.model_attr.keys())
+ self.attr_info_rule = "[\s\S]*SMART Attributes Data Structure revision number: 1|SMART Error Log Version[\s\S]*"
+ self.dev = diskdev
+ # Generic part
+ self.fetch_generic_ssd_info(diskdev)
+ self.parse_generic_ssd_info()
+ self.fetch_vendor_ssd_info(diskdev, "Generic")
+
+ # Known vendor part
+ if self.model:
+ model_short = self.model.split()[0]
+ if model_short in self.vendor_ssd_utility:
+ self.fetch_vendor_ssd_info(diskdev, model_short)
+ self.parse_vendor_ssd_info(model_short)
+ else:
+ # No handler registered for this disk model
+ pass
+ else:
+ # Failed to get disk model
+ self.model = "Unknown"
+
+ def _execute_shell(self, cmd):
+ process = subprocess.Popen(cmd.split(), universal_newlines=True, stdout=subprocess.PIPE)
+ output, error = process.communicate()
+ exit_code = process.returncode
+ if exit_code:
+ return None
+ return output
+
+ def _parse_re(self, pattern, buffer):
+ res_list = re.findall(pattern, str(buffer))
+ return res_list[0] if res_list else NOT_AVAILABLE
+
+ def fetch_generic_ssd_info(self, diskdev):
+ self.ssd_info = self._execute_shell(self.vendor_ssd_utility["Generic"]["utility"].format(diskdev))
+
+ # Health and temperature values may be overwritten with vendor specific data
+ def parse_generic_ssd_info(self):
+ if "nvme" in self.dev:
+ self.model = self._parse_re('Model Number:\s*(.+?)\n', self.ssd_info)
+
+ health_raw = self._parse_re('Percentage Used\s*(.+?)\n', self.ssd_info)
+ if health_raw == NOT_AVAILABLE:
+ self.health = NOT_AVAILABLE
+ else:
+ health_raw = health_raw.split()[-1]
+ self.health = 100 - float(health_raw.strip('%'))
+
+ temp_raw = self._parse_re('Temperature\s*(.+?)\n', self.ssd_info)
+ if temp_raw == NOT_AVAILABLE:
+ self.temperature = NOT_AVAILABLE
+ else:
+ temp_raw = temp_raw.split()[-2]
+ self.temperature = float(temp_raw)
+ else:
+ self.model = self._parse_re('Device Model:\s*(.+?)\n', self.ssd_info)
+ model_key = ""
+ for key in self.key_list:
+ if re.search(key, self.model):
+ model_key = key
+ break
+ if model_key != "":
+ self.remaining_life = self._parse_re(self.model_attr[model_key]["remainingLife"], re.sub(self.attr_info_rule,"",self.ssd_info)).split()[2]
+ self.temperature = self._parse_re(self.model_attr[model_key]["temperature"], re.sub(self.attr_info_rule,"",self.ssd_info)).split()[8]
+ self.health = self.remaining_life
+ # Get the LITEON ssd health value by (PE CYCLE - AVG ERASE CYCLE )/(PE CYCLE)
+ if model_key in ["ER2-GD", "AF2MA31DTDLT"]:
+ avg_erase = int(self._parse_re('\n173\s+(.+?)\n' ,re.sub(self.attr_info_rule,"",self.ssd_info)).split()[-1])
+ self.health = int(round((PE_CYCLE - avg_erase)/PE_CYCLE*100,0))
+ if self.remaining_life != NOT_AVAILABLE and int(self.remaining_life) < FAIL_PERCENT:
+ self.remaining_life = "Fail"
+ self.sata_rate = self._parse_re('SATA Version is:.*current: (.+?)\)\n', self.ssd_info)
+ self.serial = self._parse_re('Serial Number:\s*(.+?)\n', self.ssd_info)
+ self.firmware = self._parse_re('Firmware Version:\s*(.+?)\n', self.ssd_info)
+
+ def parse_innodisk_info(self):
+ if self.vendor_ssd_info:
+ self.health = self._parse_re('Health:\s*(.+?)%', self.vendor_ssd_info)
+ self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info)
+ else:
+ if self.health == NOT_AVAILABLE:
+ health_raw = self.parse_id_number(INNODISK_HEALTH_ID)
+ self.health = health_raw.split()[-1]
+ if self.temperature == NOT_AVAILABLE:
+ temp_raw = self.parse_id_number(INNODISK_TEMPERATURE_ID)
+ self.temperature = temp_raw.split()[-6]
+
+ def parse_virtium_info(self):
+ if self.vendor_ssd_info:
+ self.temperature = self._parse_re('Temperature_Celsius\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
+ nand_endurance = self._parse_re('NAND_Endurance\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
+ avg_erase_count = self._parse_re('Average_Erase_Count\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info)
+ try:
+ self.health = 100 - (float(avg_erase_count) * 100 / float(nand_endurance))
+ except (ValueError, ZeroDivisionError):
+ # Invalid avg_erase_count or nand_endurance.
+ pass
+
+ def fetch_vendor_ssd_info(self, diskdev, model):
+ self.vendor_ssd_info = self._execute_shell(self.vendor_ssd_utility[model]["utility"].format(diskdev))
+
+ def parse_vendor_ssd_info(self, model):
+ self.vendor_ssd_utility[model]["parser"]()
+
+ def check_readonly2(self, partition, filesystem):
+ # parse mount cmd output info
+ mount_info = self._execute_shell(MOUNT_CMD)
+ for line in mount_info.split('\n'):
+ column_list = line.split()
+ if line == '':
+ continue
+ if column_list[0] == partition and column_list[2] == filesystem:
+ if column_list[5].split(',')[0][1:] == "ro":
+ return partition
+ else:
+ return NOT_AVAILABLE
+ return NOT_AVAILABLE
+
+ def check_readonly(self, partition, filesystem):
+ ret = os.access(filesystem, os.W_OK)
+ if ret == False:
+ return partition
+ else:
+ return NOT_AVAILABLE
+
+ def get_health(self):
+ """
+ Retrieves current disk health in percentages
+
+ Returns:
+ A float number of current ssd health
+ e.g. 83.5
+ """
+ if self.health == 'N/A':
+ return "NA"
+ else:
+ return float(self.health)
+
+ def get_temperature(self):
+ """
+ Retrieves current disk temperature in Celsius
+
+ Returns:
+ A float number of current temperature in Celsius
+ e.g. 40.1
+ """
+ if self.temperature == 'N/A':
+ return 'NA'
+ else:
+ return float(self.temperature)
+
+ def get_model(self):
+ """
+ Retrieves model for the given disk device
+
+ Returns:
+ A string holding disk model as provided by the manufacturer
+ """
+ return self.model
+
+ def get_firmware(self):
+ """
+ Retrieves firmware version for the given disk device
+
+ Returns:
+ A string holding disk firmware version as provided by the manufacturer
+ """
+ return self.firmware
+
+ def get_serial(self):
+ """
+ Retrieves serial number for the given disk device
+
+ Returns:
+ A string holding disk serial number as provided by the manufacturer
+ """
+ return self.serial
+ def get_sata_rate(self):
+ """
+ Retrieves SATA rate for the given disk device
+ Returns:
+ A string holding current SATA rate as provided by the manufacturer
+ """
+ return self.sata_rate
+ def get_remaining_life(self):
+ """
+ Retrieves remaining life for the given disk device
+ Returns:
+ A string holding disk remaining life as provided by the manufacturer
+ """
+ return self.remaining_life
+ def get_vendor_output(self):
+ """
+ Retrieves vendor specific data for the given disk device
+
+ Returns:
+ A string holding some vendor specific disk information
+ """
+ return self.vendor_ssd_info
+
+ def parse_id_number(self, id):
+ return self._parse_re('{}\s*(.+?)\n'.format(id), self.ssd_info)
+
+ def get_readonly_partition(self):
+ """
+ Check the partition mount filesystem is readonly status,then output the result.
+ Returns:
+ The readonly partition list
+ """
+
+ ro_partition_list = []
+ partition_list = []
+
+ # parse fdisk cmd output info
+ disk_info = self._execute_shell(DISK_LIST_CMD)
+ begin_flag = False
+ for line in disk_info.split('\n'):
+ if line == "Device":
+ begin_flag = True
+ continue
+ if begin_flag:
+ if line != "":
+ partition_list.append(line)
+ else:
+ break
+
+ # parse df cmd output info
+ disk_free = self._execute_shell(DISK_FREE_CMD)
+ disk_dict = {}
+ line_num = 0
+ for line in disk_free.split('\n'):
+ line_num = line_num + 1
+ if line_num == 1 or line == "":
+ continue
+ column_list = line.split()
+ disk_dict[column_list[0]] = column_list[5]
+
+ # get partition which is readonly
+ for partition in partition_list:
+ if partition in disk_dict:
+ ret = self.check_readonly(partition, disk_dict[partition])
+ if (ret != NOT_AVAILABLE):
+ ro_partition_list.append(ret)
+
+ return ro_partition_list
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/pmon_daemon_control.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/pmon_daemon_control.json
new file mode 100644
index 000000000000..94592fa8cebc
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/pmon_daemon_control.json
@@ -0,0 +1,3 @@
+{
+ "skip_ledd": true
+}
diff --git a/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/system_health_monitoring_config.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/system_health_monitoring_config.json
new file mode 100755
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index c9660299ed7e..a019810887a7 100755
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -79,6 +79,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(DELTA_AGC032_PLATFORM_MODULE) \
$(RUIJIE_B6510_48VS8CQ_PLATFORM_MODULE) \
$(RAGILE_RA_B6510_48V8C_PLATFORM_MODULE) \
+ $(MICAS_M2_W6510_48V8C_PLATFORM_MODULE) \
+ $(MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE) \
$(NOKIA_IXR7250_PLATFORM_MODULE) \
$(TENCENT_TCS8400_PLATFORM_MODULE) \
$(TENCENT_TCS9400_PLATFORM_MODULE) \
diff --git a/platform/broadcom/platform-modules-micas.dep b/platform/broadcom/platform-modules-micas.dep
new file mode 100644
index 000000000000..6ae59a668b27
--- /dev/null
+++ b/platform/broadcom/platform-modules-micas.dep
@@ -0,0 +1,9 @@
+MPATH := $($(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)_SRC_PATH)
+DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/broadcom/platform-modules-micas.mk platform/broadcom/platform-modules-micas.dep
+DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
+DEP_FILES += $(addprefix $(MPATH)/,$(shell cd $(MPATH) && git ls-files))
+
+
+$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)_CACHE_MODE := GIT_CONTENT_SHA
+$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
+$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)_DEP_FILES := $(DEP_FILES)
diff --git a/platform/broadcom/platform-modules-micas.mk b/platform/broadcom/platform-modules-micas.mk
new file mode 100644
index 000000000000..dffad30f1590
--- /dev/null
+++ b/platform/broadcom/platform-modules-micas.mk
@@ -0,0 +1,19 @@
+## M2-W6510-48V8C
+MICAS_M2_W6510_48V8C_PLATFORM_MODULE_VERSION = 1.0
+export MICAS_M2_W6510_48V8C_PLATFORM_MODULE_VERSION
+
+MICAS_M2_W6510_48V8C_PLATFORM_MODULE = platform-modules-micas-m2-w6510-48v8c_$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE_VERSION)_amd64.deb
+$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-micas
+$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) $(PDDF_PLATFORM_MODULE)
+$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)_PLATFORM = x86_64-micas_m2-w6510-48v8c-r0
+SONIC_DPKG_DEBS += $(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)
+SONIC_STRETCH_DEBS += $(MICAS_M2_W6510_48V8C_PLATFORM_MODULE)
+
+## M2-W6520-24DC8QC
+MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE_VERSION = 1.0
+export MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE_VERSION
+
+MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE = platform-modules-micas-m2-w6520-24dc8qc_$(MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE_VERSION)_amd64.deb
+$(MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE)_PLATFORM = x86_64-micas_m2-w6520-24dc8qc-r0
+$(eval $(call add_extra_package,$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE),$(MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE)))
+
diff --git a/platform/broadcom/rules.dep b/platform/broadcom/rules.dep
index e27e370b9a27..51cca1baacce 100644
--- a/platform/broadcom/rules.dep
+++ b/platform/broadcom/rules.dep
@@ -20,6 +20,7 @@ include $(PLATFORM_PATH)/platform-modules-quanta.dep
#include $(PLATFORM_PATH)/platform-modules-ragile.dep
include $(PLATFORM_PATH)/platform-modules-ruijie.dep
include $(PLATFORM_PATH)/platform-modules-brcm-xlr-gts.dep
+include $(PLATFORM_PATH)/platform-modules-micas.dep
include $(PLATFORM_PATH)/docker-syncd-brcm.dep
include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.dep
include $(PLATFORM_PATH)/docker-saiserver-brcm.dep
diff --git a/platform/broadcom/rules.mk b/platform/broadcom/rules.mk
index 9a506192d605..15073c3d89a0 100755
--- a/platform/broadcom/rules.mk
+++ b/platform/broadcom/rules.mk
@@ -22,6 +22,7 @@ include $(PLATFORM_PATH)/platform-modules-quanta.mk
#include $(PLATFORM_PATH)/platform-modules-ragile.mk
#include $(PLATFORM_PATH)/platform-modules-tencent.mk
#include $(PLATFORM_PATH)/platform-modules-ufispace.mk
+include $(PLATFORM_PATH)/platform-modules-micas.mk
include $(PLATFORM_PATH)/docker-syncd-brcm.mk
include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk
include $(PLATFORM_PATH)/docker-saiserver-brcm.mk
diff --git a/platform/broadcom/sonic-platform-modules-micas/LICENSE b/platform/broadcom/sonic-platform-modules-micas/LICENSE
new file mode 100644
index 000000000000..5681cac34476
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/LICENSE
@@ -0,0 +1,14 @@
+Copyright (C) 2016 Microsoft, 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 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.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/Makefile
new file mode 100755
index 000000000000..385dae0884fb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/Makefile
@@ -0,0 +1,41 @@
+PWD = $(shell pwd)
+CC ?=gcc
+INSTALL_MOD_DIR ?=extra
+KVERSION ?= $(shell uname -r)
+KERNEL_SRC ?= /lib/modules/$(KVERSION)
+EXTRA_CFLAGS:= -I$(M)/include
+EXTRA_CFLAGS+= -Wall
+SUB_BUILD_DIR = $(PWD)/build
+DIR_KERNEL_SRC = $(PWD)/modules
+SCRIPT_DIR = $(PWD)/script
+SERVICE_DIR = $(PWD)/service
+BLACK_DRIVER_CONF_DIR = $(PWD)/modprobe_conf
+
+app_dir = $(PWD)/app
+app_build_dir = $(app_dir)/build
+modules_build_dir = $(DIR_KERNEL_SRC)/build
+
+INSTALL_MODULE_DIR = $(SUB_BUILD_DIR)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR)
+INSTALL_SCRIPT_DIR = $(SUB_BUILD_DIR)/usr/local/bin
+INSTALL_SERVICE_DIR = $(SUB_BUILD_DIR)/lib/systemd/system
+INSTALL_LIB_DIR = $(SUB_BUILD_DIR)/usr/lib/python3/dist-packages
+INSTALL_BLACK_DRIVER = $(SUB_BUILD_DIR)/etc/modprobe.d
+
+all:
+ $(MAKE) -C $(app_dir)
+ $(MAKE) -C $(DIR_KERNEL_SRC)
+ @if [ ! -d ${INSTALL_MODULE_DIR} ]; then mkdir -p ${INSTALL_MODULE_DIR} ;fi
+ @if [ ! -d ${INSTALL_SCRIPT_DIR} ]; then mkdir -p ${INSTALL_SCRIPT_DIR} ;fi
+ @if [ ! -d ${INSTALL_SERVICE_DIR} ]; then mkdir -p ${INSTALL_SERVICE_DIR} ;fi
+ @if [ ! -d ${INSTALL_LIB_DIR} ]; then mkdir -p ${INSTALL_LIB_DIR} ;fi
+ @if [ -d $(PWD)/lib/ ]; then cp -r $(PWD)/lib/* ${INSTALL_LIB_DIR} ;fi
+ @if [ -d $(PWD)/sonic_platform/ ]; then cp -rf $(PWD)/sonic_platform ${INSTALL_LIB_DIR} ;fi
+ cp -r $(modules_build_dir)/*.ko $(INSTALL_MODULE_DIR)
+ cp -r $(app_dir)/build/app/* $(INSTALL_SCRIPT_DIR)
+ cp -r $(SCRIPT_DIR)/* $(INSTALL_SCRIPT_DIR)
+ cp -r $(SERVICE_DIR)/* $(INSTALL_SERVICE_DIR)
+ @if [ -d $(INSTALL_SCRIPT_DIR) ]; then chmod +x $(INSTALL_SCRIPT_DIR)/* ;fi
+ @if [ ! -d ${INSTALL_BLACK_DRIVER} ]; then mkdir -p ${INSTALL_BLACK_DRIVER} ;fi
+ cp -r $(BLACK_DRIVER_CONF_DIR)/* $(INSTALL_BLACK_DRIVER)
+clean:
+ rm -rf $(SUB_BUILD_DIR)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/app/Makefile
new file mode 100644
index 000000000000..25ba3c5a9156
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/Makefile
@@ -0,0 +1,25 @@
+pes_parent_dir:=$(shell pwd)/$(lastword $(MAKEFILE_LIST))
+pes_parent_dir:=$(shell dirname $(pes_parent_dir))
+
+SUBDIRS=$(shell ls -l | grep ^d | awk '{if($$9 != "build") print $$9}')
+INC = -I./inc
+
+COMMON_OUT_PUT := $(shell pwd)/build
+common_out_put_dir := $(COMMON_OUT_PUT)/app
+common_module_dir := $(COMMON_OUT_PUT)/module/
+export common_out_put_dir common_module_dir
+
+all : CHECK $(SUBDIRS)
+CHECK :
+ @echo $(pes_parent_dir)
+
+$(SUBDIRS):ECHO
+ #@echo $@
+ make -C $@
+
+ECHO:
+ @echo $(SUBDIRS)
+
+.PHONY : clean
+clean :
+ -rm -rf $(COMMON_OUT_PUT)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/Makefile
new file mode 100644
index 000000000000..e4078716eb33
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/Makefile
@@ -0,0 +1,30 @@
+top_srcdir:=$(shell pwd)
+#include $(top_srcdir)/Rules.mk
+DIR=$(shell pwd)
+BUILD_OUTPUT=$(DIR)/tmp
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c, $(BUILD_OUTPUT)/%.o, $(SRCS))
+DEPS=$(patsubst %.o, %.d, $(OBJS))
+CFLAGS+=-Wall -W -g -I$(DIR)/include
+LDFLAGS=
+PROGRAM=dfd_debug
+
+.PHONY: all
+
+all:$(OBJS)
+ $(CC) $(OBJS) $(LDFLAGS) -o $(BUILD_OUTPUT)/$(PROGRAM)
+ @if [ ! -d ${common_out_put_dir} ]; then mkdir -p ${common_out_put_dir} ;fi
+ cp -p $(BUILD_OUTPUT)/$(PROGRAM) $(common_out_put_dir)
+
+$(OBJS):$(SRCS)
+ @if [ ! -d ${BUILD_OUTPUT} ]; then mkdir -p ${BUILD_OUTPUT} ;fi
+ $(CC) -c $(CFLAGS) $(INCLUDE) $(*F).c -o $@
+
+.PHONY: install
+install:
+ @mkdir -p $(common_out_put_dir)
+ cp -p $(BUILD_OUTPUT)/$(PROGRAM) $(common_out_put_dir)
+
+rebuild: clean all
+clean:
+ @rm -rf $(BUILD_OUTPUT)/*
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_debug.c b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_debug.c
new file mode 100644
index 000000000000..93ed6066efed
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_debug.c
@@ -0,0 +1,43 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "dfd_utest.h"
+
+int g_dfd_debug_sw = 0;
+int g_dfd_debugpp_sw = 0;
+
+void dfd_debug_set_init(void)
+{
+ FILE *fp;
+ char buf[10];
+
+ mem_clear(buf, sizeof(buf));
+ fp = fopen(DFD_DEBUGP_DEBUG_FILE, "r");
+ if (fp != NULL) {
+
+ g_dfd_debug_sw = 1;
+ fclose(fp);
+ }
+
+ fp = fopen(DFD_DEBUGPP_DEBUG_FILE, "r");
+ if (fp != NULL) {
+
+ g_dfd_debugpp_sw = 1;
+ fclose(fp);
+ }
+
+ return;
+}
+
+int main(int argc, char* argv[])
+{
+ dfd_debug_set_init();
+ dfd_utest_cmd_main(argc, argv);
+
+ return 0;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_utest.c b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_utest.c
new file mode 100644
index 000000000000..c82b0baad4c3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_utest.c
@@ -0,0 +1,2121 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "dfd_utest.h"
+
+#define DFD_UTEST_MAX_RDWR_NUM (256)
+#define DFD_UTEST_DEFAULT_WR_NUM (1)
+
+#define DEV_MEM_NAME "/dev/mem"
+#define DEV_KMEM_NAME "/dev/kmem"
+
+#define WIDTH_1Byte (1)
+#define WIDTH_2Byte (2)
+#define WIDTH_4Byte (4)
+#define DFD_UTEST_MAX_BIT_WIDTH (4)
+
+struct phydev_user_info {
+ int phy_index;
+ uint32_t regnum;
+ uint32_t regval;
+};
+
+#define CMD_PHY_LIST _IOR('P', 0, struct phydev_user_info)
+#define CMD_PHY_READ _IOR('P', 1, struct phydev_user_info)
+#define CMD_PHY_WRITE _IOR('P', 2, struct phydev_user_info)
+
+struct mdio_dev_user_info {
+ int mdio_index;
+ int phyaddr;
+ uint32_t regnum;
+ uint32_t regval;
+};
+
+#define CMD_MDIO_LIST _IOR('M', 0, struct mdio_dev_user_info)
+#define CMD_MDIO_READ _IOR('M', 1, struct mdio_dev_user_info)
+#define CMD_MDIO_WRITE _IOR('M', 2, struct mdio_dev_user_info)
+
+#ifdef DFD_UTEST_ITEM
+#undef DFD_UTEST_ITEM
+#endif
+#define DFD_UTEST_ITEM(_id, _type_str, _help_info, _help_info_detail) {_id, #_type_str, dfd_utest_##_type_str, _help_info, _help_info_detail},
+static dfd_utest_t g_dfd_unit_test[] = {
+ DFD_UTEST_ITEM_ALL
+};
+
+static int g_sys_page_size;
+#define SYS_PAGE_SIZE g_sys_page_size
+#define SYS_PAGE_MASK (~(SYS_PAGE_SIZE - 1))
+
+void dfd_utest_print_cmd(int argc, char* argv[])
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (i != 1) {
+ printf(" ");
+ }
+ printf("%s", argv[i]);
+ }
+ return;
+}
+
+void dfd_utest_print_all_help(void)
+{
+ int i, tbl_size;
+
+ tbl_size = sizeof(g_dfd_unit_test) / sizeof(g_dfd_unit_test[0]);
+
+ for (i = 0; i < tbl_size; i++) {
+ printf("%-20s\t\t\t%s\r\n", g_dfd_unit_test[i].type_str, g_dfd_unit_test[i].help_info);
+ }
+
+ return;
+}
+
+void dfd_utest_printf_single_help(int utest_type)
+{
+ int i, tbl_size;
+
+ tbl_size = sizeof(g_dfd_unit_test) / sizeof(g_dfd_unit_test[0]);
+ for (i = 0; i < tbl_size; i++) {
+ if (g_dfd_unit_test[i].utest_type == utest_type) {
+ printf("%-20s\t\t\t%s\r\n", g_dfd_unit_test[i].type_str, g_dfd_unit_test[i].help_info_detail);
+ return;
+ }
+ }
+
+ DFD_DEBUG_DBG("type: %d not match.\n", utest_type);
+ return;
+
+}
+
+void dfd_utest_printf_reg(uint8_t *buf, int buf_len, uint32_t offset_addr)
+{
+ int i, j, tmp;
+
+ j = offset_addr % 16;
+ tmp = j;
+ offset_addr -= j;
+ printf("\n ");
+
+ for (i = 0; i < 16; i++) {
+ printf("%2x ", i);
+ }
+
+ for (i = 0; i < buf_len + j; i++) {
+ if ((i % 16) == 0) {
+ printf("\n0x%08x ", offset_addr);
+ offset_addr = offset_addr + 16;
+ }
+ if (tmp) {
+ printf(" ");
+ tmp--;
+ } else {
+ printf("%02x ", buf[i-j]);
+ }
+ }
+
+ printf("\n");
+ return;
+}
+
+#define I2C_RETRIES 0x0701
+#define I2C_TIMEOUT 0x0702
+#define I2C_RDWR 0x0707
+
+#define I2C_SLAVE 0x0703 /* Use this slave address */
+
+#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it
+ is already in use by a driver! */
+#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */
+#define I2C_SMBUS 0x0720 /* SMBus transfer */
+
+struct i2c_msg
+{
+ unsigned short addr;
+ unsigned short flags;
+#define I2C_M_TEN 0x0010
+#define I2C_M_RD 0x0001
+ unsigned short len;
+ unsigned char *buf;
+};
+
+struct i2c_rdwr_ioctl_data
+{
+ struct i2c_msg *msgs;
+ int nmsgs;
+
+};
+
+#define DFD_I2C_SHORT_ADDR_TYPE 0
+#define DFD_I2C_RETRY_SLEEP_TIME (10000) /* 10ms */
+#define DFD_I2C_RETRY_TIME (50000 / DFD_I2C_RETRY_SLEEP_TIME)
+/* i2c_smbus_xfer read or write markers */
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+/* SMBus transaction types (size parameter in the above functions)
+ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_PROC_CALL 4
+#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,36)
+/* fix tjm */
+
+#ifndef __ASSEMBLY__
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+typedef __signed__ long __s64;
+typedef unsigned long __u64;
+
+#endif /* __ASSEMBLY__ */
+
+#else
+/* do noting add tjm */
+#endif
+
+/*
+ * Data for SMBus Messages
+ */
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+union i2c_smbus_data {
+ __u8 byte;
+ __u16 word;
+ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+ /* and one more for user-space compatibility */
+};
+
+/* This is the structure as used in the I2C_SMBUS ioctl call */
+struct i2c_smbus_ioctl_data {
+ __u8 read_write;
+ __u8 command;
+ __u32 size;
+ union i2c_smbus_data *data;
+};
+int32_t dfd_read_port_i2c_one_time_smbus(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr,
+ uint8_t *recv_buf, int32_t size, int addr_type)
+{
+ union i2c_smbus_data data;
+ struct i2c_smbus_ioctl_data ioctl_data;
+ unsigned long addr = dev_addr;
+ int fd;
+ int rc;
+ int rv;
+ int i;
+
+ mem_clear(&ioctl_data, sizeof(struct i2c_smbus_ioctl_data));
+ if (i2c_name == NULL || recv_buf == NULL) {
+ DFD_DEBUG_ERROR("i2c_num = NULL, recv_buf = NULL\r\n");
+ return -1;
+ }
+
+ DFD_DEBUG_DBG("i2c name: %s, dev_addr: 0x%x, offset_addr: 0x%x, size: %d, addr_type: %d.\n", i2c_name, dev_addr,
+ offset_addr, size, addr_type);
+
+ rv = 0;
+ fd = open(i2c_name, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ DFD_DEBUG_ERROR("i2c open fail fd %d\n", fd);
+ rv = fd;
+ goto err;
+ }
+ if (ioctl(fd, I2C_SLAVE_FORCE , addr) < 0) {
+ DFD_DEBUG_ERROR("ioctl 2C_SLAVE_FORCE %d.\n", errno);
+ rv =-1;
+ goto fail;
+ }
+ for (i = 0 ;i < size; i++) {
+ data.byte = 0;
+ ioctl_data.read_write = I2C_SMBUS_READ;
+ ioctl_data.command = (offset_addr + i);
+ ioctl_data.size = I2C_SMBUS_BYTE_DATA;
+ ioctl_data.data= &data;
+
+ rc = ioctl(fd, I2C_SMBUS, &ioctl_data);
+ if (rc < 0) {
+ DFD_DEBUG_ERROR("read, I2C_SMBUS failed: %d.\n", errno);
+ rv = -1;
+ goto fail;
+ }
+ *(recv_buf + i) = data.byte;
+ }
+ fail:
+ close(fd);
+ err:
+ return rv;
+
+}
+
+int32_t dfd_read_port_i2c_one_time(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr,
+ uint8_t *recv_buf, int32_t size, int addr_type)
+{
+
+ int32_t fd, rv;
+ struct i2c_rdwr_ioctl_data ioctl_data;
+ struct i2c_msg msgs[2];
+ uint8_t buf[2];
+
+ if (i2c_name == NULL || recv_buf == NULL) {
+ DFD_DEBUG_ERROR("i2c_num = NULL, recv_buf = NULL\r\n");
+ return -1;
+ }
+
+ DFD_DEBUG_DBG("i2c name %s, dev_addr 0x%x, offset_addr 0x%x, size %d, addr_type %d.\n", i2c_name, dev_addr,
+ offset_addr, size, addr_type);
+
+ rv = 0;
+ fd = open(i2c_name, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ DFD_DEBUG_ERROR("i2c open fail fd %d\n", fd);
+ return -1;
+ }
+ mem_clear(&ioctl_data, sizeof(ioctl_data));
+ mem_clear(msgs, sizeof(msgs));
+ mem_clear(buf, sizeof(buf));
+ if (ioctl(fd, I2C_SLAVE, dev_addr) < 0) {
+
+ DFD_DEBUG_ERROR("%s %dioctl fail(ret:%d, errno:%s)!\r\n", __func__ , __LINE__, rv, strerror(errno));
+ rv = -1;
+ goto fail;
+ }
+
+ buf[0] = (uint8_t)(offset_addr);
+ msgs[0].addr= dev_addr;
+ msgs[0].len= 2;
+ msgs[0].buf= buf;
+ msgs[1].addr= dev_addr;
+ msgs[1].flags|= I2C_M_RD;
+ msgs[1].len= 1;
+ msgs[1].buf= recv_buf;
+ ioctl_data.nmsgs= 1;
+ ioctl_data.msgs= msgs;
+
+ rv = ioctl(fd, I2C_RDWR, &ioctl_data);
+ if(rv < 0) {
+ DFD_DEBUG_ERROR("%s %dioctl fail(ret:%d, errno:%s)!\r\n", __func__ , __LINE__, rv, strerror(errno));
+ goto fail;
+ }
+ ioctl_data.msgs= &msgs[1];
+ DFD_DEBUG_DBG("ioctlread, return :%d/n", ioctl(fd, I2C_RDWR, &ioctl_data));
+ DFD_DEBUG_DBG("dfd_read_port_i2c addr: 0x%X, offset: 0x%X, value: 0x%X\n", dev_addr, offset_addr, *recv_buf);
+ fail:
+ close(fd);
+ return rv;
+
+}
+
+int32_t dfd_read_port_i2c(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr,
+ uint8_t *recv_buf, int32_t size)
+{
+ int i;
+ int rv;
+
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ rv = dfd_read_port_i2c_one_time_smbus(i2c_name, dev_addr, offset_addr, recv_buf, size, DFD_I2C_SHORT_ADDR_TYPE);
+ if (rv < 0) {
+ DFD_DEBUG_ERROR("(read times %d)i2c name %s, dev_addr 0x%X, offset_addr 0x%X, addr_type %d\n", i, i2c_name, dev_addr, offset_addr, DFD_I2C_SHORT_ADDR_TYPE);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+
+ return rv;
+}
+
+int32_t dfd_write_port_i2c_one_time(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr,
+ uint8_t *write_buf, int32_t size,int addr_type)
+{
+ int32_t fd, rv;
+ int index;
+ struct i2c_smbus_ioctl_data ioctl_data;
+ union i2c_smbus_data data;
+ uint8_t addr_buf[2];
+ uint8_t write_buf_tmp[256];
+
+ if (i2c_name == NULL || write_buf == NULL ) {
+ DFD_DEBUG_ERROR("i2c_num = NULL \r\n");
+ return -1;
+ }
+
+ if (size <= 0) {
+ DFD_DEBUG_ERROR("error:size\n");
+ return -1;
+ }
+ DFD_DEBUG_DBG("i2c name %s, dev_addr 0x%x, offset_addr 0x%x, size %d, addr_type %d\n",i2c_name, dev_addr,
+ offset_addr, size, addr_type);
+ mem_clear(&ioctl_data, sizeof(ioctl_data));
+ mem_clear(addr_buf, sizeof(addr_buf));
+ mem_clear(write_buf_tmp, sizeof(write_buf_tmp));
+
+ rv = 0;
+
+ fd = open(i2c_name, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ DFD_DEBUG_ERROR("i2c open fail fd %d\n", fd);
+ return -1;
+ }
+
+ if (ioctl(fd, I2C_SLAVE_FORCE, dev_addr) < 0) {
+ DFD_DEBUG_ERROR("ioctl, I2C_SLAVE failed: %d.\n", errno);
+ rv = -1;
+ goto fail;
+ }
+
+ for (index = 0; index < size; index++) {
+ data.byte = *(write_buf + index);
+ ioctl_data.read_write = I2C_SMBUS_WRITE;
+ ioctl_data.command = (offset_addr + index);
+ ioctl_data.size = I2C_SMBUS_BYTE_DATA;
+ ioctl_data.data= &data;
+ rv = ioctl(fd, I2C_SMBUS, (unsigned long)&ioctl_data);
+ if(rv < 0) {
+ DFD_DEBUG_ERROR("ioctl fail(ret:%d, errno:%s %d) !\r\n", rv, strerror(errno),errno);
+ break;
+ }
+ DFD_DEBUG_DBG("ret:%d value:0x%02x\n", rv, data.byte);
+ usleep(5000);
+ }
+
+fail:
+ close(fd);
+ return rv;
+}
+
+int32_t dfd_write_port_i2c(char *i2c_name, uint16_t dev_addr, uint16_t offset_addr,
+ uint8_t *write_buf, int32_t size)
+{
+ int i;
+ int rv;
+
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ rv = dfd_write_port_i2c_one_time(i2c_name, dev_addr, offset_addr, write_buf,size, DFD_I2C_SHORT_ADDR_TYPE);
+ if (rv < 0) {
+ DFD_DEBUG_ERROR("(write times %d)i2c name %s, dev_addr 0x%X, offset_addr 0x%X, addr_type %d\n",
+ i, i2c_name, dev_addr, offset_addr, DFD_I2C_SHORT_ADDR_TYPE);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+
+ return rv;
+}
+
+static int dfd_read_io_port(uint16_t offset_addr, uint8_t *recv_buf, int32_t size)
+{
+ int fd;
+ int ret;
+
+ fd = open("/dev/port", O_RDWR);
+ if (fd < 0) {
+ printf("open failed ret %d.\n", fd);
+ return -1;
+ }
+
+ ret = lseek(fd, offset_addr, SEEK_SET);
+ if (ret < 0) {
+ printf("lseek failed ret %d.\n", ret);
+ goto exit;
+ }
+
+ ret = read(fd, recv_buf, size);
+ if (ret != size) {
+ printf("read failed ret %d size %d.\n", ret, size);
+ ret = -1;
+ goto exit;
+ }
+
+exit:
+ close(fd);
+ return ret;
+}
+
+static int dfd_write_io_port(uint16_t offset_addr, uint8_t *write_buf, int32_t size)
+{
+ int fd;
+ int ret;
+
+ fd = open("/dev/port", O_RDWR);
+ if (fd < 0) {
+ printf("open failed ret %d.\n", fd);
+ return -1;
+ }
+
+ ret = lseek(fd, offset_addr, SEEK_SET);
+ if (ret < 0) {
+ printf("lseek failed ret %d.\n", ret);
+ goto exit;
+ }
+
+ ret = write(fd, write_buf, size);
+ if (ret != size) {
+ printf("write failed ret %d size %d.\n", ret, size);
+ ret = -1;
+ goto exit;
+ }
+
+exit:
+ close(fd);
+ return ret;
+}
+
+static int dfd_process_mem(char *dev_name, char is_wr, char width, off_t offset, uint8_t *buf, int32_t size)
+{
+ int mfd, ret = 0;
+ void *base;
+ int i, j;
+ unsigned int val;
+ off_t map_offset;
+ size_t map_size;
+
+ if (size & (width - 1)) {
+ printf("size %d invalid.\n", size);
+ return -1;
+ }
+
+ mfd = open(dev_name, O_RDWR);
+ if (mfd < 0) {
+ printf("Cannot open %s.\n", dev_name);
+ return -1;
+ }
+
+ g_sys_page_size = getpagesize();
+ map_offset = offset & SYS_PAGE_MASK;
+ map_size = size + offset - map_offset;
+ base = mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, map_offset);
+ if (base == MAP_FAILED) {
+ printf("mmap offset 0x%lx failed error(%s).\n", map_offset, strerror(errno));
+ close(mfd);
+ return -1;
+ }
+ printf("width %d map_offset 0x%lx, offset 0x%lx, mmap base %p, g_sys_page_size %d\n",
+ width, map_offset, offset, base, g_sys_page_size);
+
+ if (is_wr) {
+ for (i = 0; i < size; i = i + width) {
+ val = 0;
+ for (j = 0; j < width; j++) {
+ val |= buf[i + j] << (8 * j);
+ }
+ switch (width) {
+ case 1:
+ *((volatile unsigned char*)(base + i + offset - map_offset)) = val;
+ break;
+ case 2:
+ *((volatile unsigned short*)(base + i + offset - map_offset)) = val;
+ break;
+ case 4:
+ *((volatile unsigned int*)(base + i + offset - map_offset)) = val;
+ break;
+ default:
+ ret = -1;
+ printf("Not support width %d.\n", width);
+ goto exit;
+ }
+ }
+ } else {
+ for (i = 0; i < size; i = i + width) {
+ switch (width) {
+ case 1:
+ val = *((volatile unsigned char*)(base + i + offset - map_offset));
+ break;
+ case 2:
+ val = *((volatile unsigned short*)(base + i + offset - map_offset));
+ break;
+ case 4:
+ val = *((volatile unsigned int*)(base + i + offset - map_offset));
+ break;
+ default:
+ ret = -1;
+ printf("Not support width %d.\n", width);
+ goto exit;
+ }
+ for (j = 0; j < width; j++) {
+ buf[i + j] = (val >> (8 * j)) & 0xff;
+ }
+ }
+ }
+exit:
+ munmap(base, map_size);
+ close(mfd);
+ return ret;
+}
+
+int32_t dfd_i2c_gen_read_one_time(char *i2c_path, uint32_t dev_addr, uint32_t addr_bitwidth,
+ uint32_t offset_addr, uint8_t *recv_buf, int32_t rd_len)
+{
+ int32_t fd, rv, i;
+ struct i2c_rdwr_ioctl_data ioctl_data;
+ struct i2c_msg msgs[2];
+ uint8_t buf[DFD_UTEST_MAX_BIT_WIDTH];
+
+ fd = open(i2c_path, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ DFD_DEBUG_ERROR("i2c open fail fd:%d\n", fd);
+ return -1;
+ }
+ mem_clear(&ioctl_data, sizeof(ioctl_data));
+ mem_clear(msgs, sizeof(msgs));
+ mem_clear(buf, sizeof(buf));
+
+ i = 0;
+
+ switch (addr_bitwidth) {
+ case WIDTH_4Byte:
+ buf[i++] = (offset_addr >> 24) & 0xFF;
+ buf[i++] = (offset_addr >> 16) & 0xFF;
+ buf[i++] = (offset_addr >> 8) & 0xFF;
+ buf[i++] = offset_addr & 0xFF;
+ break;
+ case WIDTH_2Byte:
+ buf[i++] = (offset_addr >> 8) & 0xFF;
+ buf[i++] = offset_addr & 0xFF;
+ break;
+ case WIDTH_1Byte:
+ buf[i++] = offset_addr & 0xFF;
+ break;
+ default:
+ DFD_DEBUG_ERROR("Only support 1,2,4 Byte Address Width,but set %u addr_bitwidth \n", addr_bitwidth);
+ rv = -1;
+ goto fail;
+ }
+
+ msgs[0].addr = dev_addr;
+ msgs[0].flags = 0;
+ msgs[0].len = addr_bitwidth;
+ msgs[0].buf = buf;
+ msgs[1].addr = dev_addr;
+ msgs[1].flags |= I2C_M_RD;
+ msgs[1].len = rd_len;
+ msgs[1].buf = recv_buf;
+ ioctl_data.nmsgs = 2;
+ ioctl_data.msgs = msgs;
+
+ rv = ioctl(fd, I2C_RDWR, &ioctl_data);
+ if(rv < 0) {
+ DFD_DEBUG_ERROR("%s %d Error: Sending messages failed:(ret:%d, errno:%s)!\n", __func__ , __LINE__, rv, strerror(errno));
+ goto fail;
+ }
+
+fail:
+ close(fd);
+ return rv;
+}
+
+int32_t dfd_i2c_gen_read(char *i2c_path, uint32_t dev_addr, uint32_t addr_bitwidth,
+ uint32_t offset_addr, uint8_t *recv_buf, int32_t rd_len)
+{
+ int i;
+ int rv;
+
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ rv = dfd_i2c_gen_read_one_time(i2c_path, dev_addr, addr_bitwidth, offset_addr, recv_buf, rd_len);
+ if (rv < 0) {
+ DFD_DEBUG_ERROR("(read times:%d) i2c_path:%s, dev_addr:0x%x, addr_bitwidth:%u, offset_addr:0x%x, rd_len:%u\n",
+ i, i2c_path, dev_addr, addr_bitwidth, offset_addr, rd_len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+
+ return rv;
+}
+
+int dfd_utest_i2c_gen_rd(int argc, char* argv[])
+{
+ int ret;
+ uint32_t i2c_bus, dev_addr, addr_bitwidth, offset_addr, data_bitwidth, rd_len, i, j;
+ char *stopstring;
+ char i2c_path[32];
+ uint8_t tmp_value[DFD_UTEST_MAX_RDWR_NUM];
+ uint8_t rd_value[DFD_UTEST_MAX_RDWR_NUM];
+
+ if (argc != 8) {
+ DFD_DEBUG_ERROR("params error\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_GEN_RD);
+ goto exit;
+ }
+
+ i2c_bus = strtol(argv[2], &stopstring, 10);
+ dev_addr = strtol(argv[3], &stopstring, 16);
+ addr_bitwidth = strtol(argv[4], &stopstring, 10);
+ offset_addr = strtol(argv[5], &stopstring, 16);
+ data_bitwidth = strtol(argv[6], &stopstring, 10);
+ rd_len = strtol(argv[7], &stopstring, 10);
+
+ if (rd_len > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", rd_len);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_GEN_RD);
+ goto exit;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+ printf(":\n");
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus);
+ mem_clear(tmp_value, sizeof(tmp_value));
+ ret = dfd_i2c_gen_read(i2c_path, dev_addr, addr_bitwidth, offset_addr, tmp_value, rd_len);
+ if (ret < 0) {
+ printf("read failed. ret:%d\n", ret);
+ goto exit;
+ }
+
+ mem_clear(rd_value, sizeof(rd_value));
+ if (data_bitwidth == WIDTH_1Byte) {
+ memcpy(rd_value, tmp_value, rd_len);
+ } else {
+ for (i = 0; i < rd_len; i += data_bitwidth) {
+ for (j = 0; (j < data_bitwidth) && (i + j < rd_len); j++) {
+ rd_value[i + data_bitwidth - j - 1] = tmp_value[i + j];
+ }
+ }
+ }
+
+ dfd_utest_printf_reg(rd_value, rd_len, offset_addr);
+
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int32_t dfd_i2c_gen_write_one_time(char *i2c_path, uint32_t dev_addr, uint32_t addr_bitwidth,
+ uint32_t offset_addr, uint8_t *wr_value, uint32_t wr_len)
+{
+ int32_t fd, rv, i;
+ struct i2c_rdwr_ioctl_data ioctl_data;
+ struct i2c_msg msgs[1];
+ uint8_t buf[DFD_UTEST_MAX_BIT_WIDTH + DFD_UTEST_MAX_RDWR_NUM];
+
+ fd = open(i2c_path, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ DFD_DEBUG_ERROR("i2c open fail fd %d\n", fd);
+ return -1;
+ }
+ mem_clear(&ioctl_data, sizeof(ioctl_data));
+ mem_clear(msgs, sizeof(msgs));
+ mem_clear(buf, sizeof(buf));
+
+ i = 0;
+
+ switch (addr_bitwidth) {
+ case WIDTH_4Byte:
+ buf[i++] = (offset_addr >> 24) & 0xFF;
+ buf[i++] = (offset_addr >> 16) & 0xFF;
+ buf[i++] = (offset_addr >> 8) & 0xFF;
+ buf[i++] = offset_addr & 0xFF;
+ break;
+ case WIDTH_2Byte:
+ buf[i++] = (offset_addr >> 8) & 0xFF;
+ buf[i++] = offset_addr & 0xFF;
+ break;
+ case WIDTH_1Byte:
+ buf[i++] = offset_addr & 0xFF;
+ break;
+ default:
+ DFD_DEBUG_ERROR("Only support 1,2,4 Byte Address Width,but set %u addr_bitwidth \r\n", addr_bitwidth);
+ rv = -1;
+ goto fail;
+ }
+
+ memcpy(buf + addr_bitwidth, wr_value, wr_len);
+
+ msgs[0].addr= dev_addr;
+ msgs[0].flags = 0;
+ msgs[0].len= addr_bitwidth + wr_len;
+ msgs[0].buf= buf;
+
+ ioctl_data.nmsgs= 1;
+ ioctl_data.msgs= msgs;
+
+ rv = ioctl(fd, I2C_RDWR, &ioctl_data);
+ if(rv < 0) {
+ DFD_DEBUG_ERROR("%s %dError: Sending messages failed:(ret:%d, errno:%s)!\n", __func__ , __LINE__, rv, strerror(errno));
+ goto fail;
+ } else if (rv < ioctl_data.nmsgs) {
+ DFD_DEBUG_ERROR("%s %dWarning: only %d/%d messages were sent\n", __func__ , __LINE__, rv, ioctl_data.nmsgs);
+ }
+
+fail:
+ close(fd);
+ return rv;
+}
+
+int32_t dfd_i2c_gen_write(char *i2c_path, uint32_t dev_addr, uint32_t addr_bitwidth,
+ uint32_t offset_addr, uint8_t *wr_value, uint32_t wr_len)
+{
+ int i;
+ int rv;
+
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ rv = dfd_i2c_gen_write_one_time(i2c_path, dev_addr, addr_bitwidth, offset_addr, wr_value, wr_len);
+ if (rv < 0) {
+ DFD_DEBUG_ERROR("(write times:%d)i2c_path:%s, dev_addr:0x%x, addr_bitwidth:%u, offset_addr:0x%x, wr_len:%u\n",
+ i, i2c_path, dev_addr, addr_bitwidth, offset_addr, wr_len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+
+ return rv;
+}
+
+int dfd_utest_i2c_gen_wr(int argc, char* argv[])
+{
+ int ret;
+ uint32_t i2c_bus, dev_addr, addr_bitwidth, offset_addr, data_bitwidth, wr_len, tmp_data, para_len, i, j;
+ char *stopstring;
+ char i2c_path[32];
+ uint8_t wr_value[DFD_UTEST_MAX_RDWR_NUM];
+
+ if (argc < 8) {
+ DFD_DEBUG_ERROR("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_GEN_WR);
+ goto exit;
+ }
+
+ i2c_bus = strtol(argv[2], &stopstring, 10);
+ dev_addr = strtol(argv[3], &stopstring, 16);
+ addr_bitwidth = strtol(argv[4], &stopstring, 10);
+ offset_addr = strtol(argv[5], &stopstring, 16);
+ data_bitwidth = strtol(argv[6], &stopstring, 10);
+
+ para_len = argc - 7;
+ wr_len = para_len * data_bitwidth;
+
+ if (wr_len > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", wr_len);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_GEN_WR);
+ goto exit;
+ }
+
+ if (data_bitwidth == WIDTH_1Byte) {
+ for (i = 0; i < para_len; i++) {
+ wr_value[i] = strtol(argv[7 + i], &stopstring, 16);
+ DFD_DEBUG_DBG(" index :%d value 0x%x\n", i , wr_value[i]);
+ }
+ } else {
+ for (i = 0; i < para_len; i++) {
+ tmp_data = strtol(argv[7 + i], &stopstring, 16);
+ DFD_DEBUG_DBG(" index :%d value 0x%x\n", i , tmp_data);
+ for (j = 0; j < data_bitwidth; j++) {
+ tmp_data = strtol(argv[7 + i], &stopstring, 16);
+ wr_value[j + i * data_bitwidth] = (tmp_data >> (24 - 8 * j)) & 0xFF;
+ }
+ }
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ printf(":\n");
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus);
+
+ ret = dfd_i2c_gen_write(i2c_path, dev_addr, addr_bitwidth, offset_addr, wr_value, wr_len);
+ if (ret < 0) {
+ printf("write failed. ret:%d\n", ret);
+ } else {
+ printf("write success\n");
+ }
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_i2c_rd(int argc, char* argv[])
+{
+ int ret;
+ uint8_t value[DFD_UTEST_MAX_RDWR_NUM];
+ uint16_t dev_addr, offset_addr;
+ char *stopstring;
+ int num, i2c_bus;
+ char i2c_path[32];
+
+ if (argc != 6) {
+ DFD_DEBUG_ERROR("params error\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_RD);
+ goto exit;
+ }
+
+ i2c_bus = strtol(argv[2], &stopstring, 10);
+ dev_addr = strtol(argv[3], &stopstring, 16);
+ offset_addr = strtol(argv[4], &stopstring, 16);
+ num = strtol(argv[5], &stopstring, 10);
+
+ if (num > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", num);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_RD);
+ goto exit;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+ printf(":\n");
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus);
+ mem_clear(value, sizeof(value));
+ ret = dfd_read_port_i2c(i2c_path, dev_addr, offset_addr, value, num);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ goto exit;
+ }
+
+ dfd_utest_printf_reg(value, num, offset_addr);
+
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+
+}
+
+int dfd_utest_i2c_wr(int argc, char* argv[])
+{
+ int ret;
+ uint16_t dev_addr, offset_addr;
+ char *stopstring;
+ int i2c_bus;
+ char i2c_path[32];
+ uint8_t wr_len,i;
+ uint8_t wr_value[DFD_UTEST_MAX_RDWR_NUM];
+
+ if (argc < 6) {
+ DFD_DEBUG_ERROR("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_WR);
+ goto exit;
+ }
+
+ wr_len = argc - 5;
+ i2c_bus = strtol(argv[2], &stopstring, 10);
+ dev_addr = strtol(argv[3], &stopstring, 16);
+ offset_addr = strtol(argv[4], &stopstring, 16);
+
+ for (i = 0; i < wr_len; i++) {
+ wr_value[i] = strtol(argv[5+i], &stopstring, 16);
+ DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]);
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ printf(":\n");
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus);
+
+ ret = dfd_write_port_i2c(i2c_path, dev_addr, offset_addr, wr_value, wr_len);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ } else {
+ printf("success\n");
+ }
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_io_rd(int argc, char* argv[])
+{
+ int ret;
+ uint8_t value[DFD_UTEST_MAX_RDWR_NUM];
+ uint16_t offset_addr;
+ char *stopstring;
+ int num;
+
+ if (argc != 4) {
+ DFD_DEBUG_ERROR("params error\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_RD);
+ goto exit;
+ }
+
+ offset_addr = strtol(argv[2], &stopstring, 16);
+ num = strtol(argv[3], &stopstring, 10);
+
+ if (num > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", num);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_RD);
+ goto exit;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+ printf(":\n");
+ mem_clear(value, sizeof(value));
+ ret = dfd_read_io_port(offset_addr, value, num);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ goto exit;
+ }
+
+ dfd_utest_printf_reg(value, num, offset_addr);
+
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_io_wr(int argc, char* argv[])
+{
+ int ret;
+ uint16_t offset_addr;
+ char *stopstring;
+ int32_t wr_len,i;
+ uint8_t wr_value[DFD_UTEST_MAX_RDWR_NUM];
+
+ if (argc < 4) {
+ DFD_DEBUG_ERROR("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_WR);
+ goto exit;
+ }
+
+ wr_len = argc - 3;
+ if (wr_len > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", wr_len);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_IO_WR);
+ goto exit;
+ }
+
+ offset_addr = strtol(argv[2], &stopstring, 16);
+
+ for (i = 0; i < wr_len; i++) {
+ wr_value[i] = strtol(argv[3 + i], &stopstring, 16);
+ DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]);
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ printf(":\n");
+ ret = dfd_write_io_port(offset_addr, wr_value, wr_len);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ } else {
+ printf("success\n");
+ }
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_phymem_rd(int argc, char* argv[])
+{
+ int ret, width;
+ uint8_t value[DFD_UTEST_MAX_RDWR_NUM];
+ off_t offset_addr;
+ char *stopstring;
+ int num;
+
+ if (argc != 5) {
+ DFD_DEBUG_ERROR("params error\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_RD);
+ goto exit;
+ }
+
+ width = strtol(argv[2], &stopstring, 10);
+ offset_addr = strtol(argv[3], &stopstring, 16);
+ num = strtol(argv[4], &stopstring, 10);
+
+ if (num > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", num);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_RD);
+ goto exit;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+ printf(":\n");
+ mem_clear(value, sizeof(value));
+ ret = dfd_process_mem(DEV_MEM_NAME, 0, width, offset_addr, value, num);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ goto exit;
+ }
+
+ dfd_utest_printf_reg(value, num, offset_addr);
+
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_phymem_wr(int argc, char* argv[])
+{
+ int ret, width;
+ off_t offset_addr;
+ char *stopstring;
+ int32_t wr_len,i;
+ uint8_t wr_value[DFD_UTEST_MAX_RDWR_NUM];
+
+ if (argc < 5) {
+ DFD_DEBUG_ERROR("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_WR);
+ goto exit;
+ }
+
+ wr_len = argc - 4;
+ if (wr_len > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", wr_len);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYMEM_WR);
+ goto exit;
+ }
+
+ width = strtol(argv[2], &stopstring, 10);
+ offset_addr = strtol(argv[3], &stopstring, 16);
+
+ for (i = 0; i < wr_len; i++) {
+ wr_value[i] = strtol(argv[4 + i], &stopstring, 16);
+ DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]);
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ printf(":\n");
+ ret = dfd_process_mem(DEV_MEM_NAME, 1, width, offset_addr, wr_value, wr_len);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ } else {
+ printf("success\n");
+ }
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_kmem_rd(int argc, char* argv[])
+{
+ int ret, width;
+ uint8_t value[DFD_UTEST_MAX_RDWR_NUM];
+ uint16_t offset_addr;
+ char *stopstring;
+ int num;
+
+ if (argc != 5) {
+ DFD_DEBUG_ERROR("params error\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_RD);
+ goto exit;
+ }
+
+ width = strtol(argv[2], &stopstring, 10);
+ offset_addr = strtol(argv[3], &stopstring, 16);
+ num = strtol(argv[4], &stopstring, 10);
+
+ if (num > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", num);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_RD);
+ goto exit;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+ printf(":\n");
+ mem_clear(value, sizeof(value));
+ ret = dfd_process_mem(DEV_KMEM_NAME, 0, width, offset_addr, value, num);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ goto exit;
+ }
+
+ dfd_utest_printf_reg(value, num, offset_addr);
+
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_kmem_wr(int argc, char* argv[])
+{
+ int ret;
+ uint16_t offset_addr, width;
+ char *stopstring;
+ int32_t wr_len,i;
+ uint8_t wr_value[DFD_UTEST_MAX_RDWR_NUM];
+
+ if (argc < 5) {
+ DFD_DEBUG_ERROR("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_WR);
+ goto exit;
+ }
+
+ wr_len = argc - 4;
+ if (wr_len > DFD_UTEST_MAX_RDWR_NUM) {
+ DFD_DEBUG_ERROR("Input num %d exceed max.\n", wr_len);
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_KMEM_WR);
+ goto exit;
+ }
+
+ width = strtol(argv[2], &stopstring, 10);
+ offset_addr = strtol(argv[3], &stopstring, 16);
+
+ for (i = 0; i < wr_len; i++) {
+ wr_value[i] = strtol(argv[4 + i], &stopstring, 16);
+ DFD_DEBUG_DBG(" index :%d value %x\n", i , wr_value[i]);
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ printf(":\n");
+ ret = dfd_process_mem(DEV_KMEM_NAME, 1, width, offset_addr, wr_value, wr_len);
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ } else {
+ printf("success\n");
+ }
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+static unsigned long dfd_utest_get_file_size(const char *path)
+{
+ unsigned long filesize;
+ struct stat statbuff;
+
+ if (stat(path, &statbuff) < 0) {
+ filesize = -1;
+ } else {
+ filesize = statbuff.st_size;
+ }
+
+ return filesize;
+}
+
+int dfd_utest_i2c_file_wr(int argc, char* argv[])
+{
+ int ret;
+ uint16_t dev_addr, offset_addr;
+ char *stopstring;
+ int i2c_bus;
+ char i2c_path[32];
+ char *file_name;
+ unsigned long filesize;
+ int fd;
+ uint8_t wr_buf[DFD_UTEST_MAX_RDWR_NUM];
+ int len;
+ int bpt; /* byte per times*/
+ int page_left;
+
+ if (argc != 7) {
+ printf("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_I2C_FILE_WR);
+ goto exit;
+ }
+
+ i2c_bus = strtol(argv[2], &stopstring, 10);
+ dev_addr = strtol(argv[3], &stopstring, 16);
+ offset_addr = strtol(argv[4], &stopstring, 16);
+ bpt = strtol(argv[5], &stopstring, 10);
+ file_name = argv[6];
+
+ if ((bpt <= 0) || (bpt > DFD_UTEST_MAX_RDWR_NUM)) {
+ bpt = DFD_UTEST_MAX_RDWR_NUM;
+ }
+
+ if ((bpt & (bpt - 1)) != 0) {
+ printf("Bytes per times %d isn't power of two.\n",bpt);
+ goto exit;
+ }
+
+ filesize = dfd_utest_get_file_size(file_name);
+ if (filesize <= 0) {
+ printf("Input invalid file %s, filesize %lu.\n", file_name, filesize);
+ goto exit;
+ }
+
+ fd = open(file_name, O_RDONLY);
+ if (fd < 0) {
+ printf("open file[%s] fail.\n", file_name);
+ goto exit;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ printf(":\n");
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", i2c_bus);
+
+ while (filesize > 0) {
+ mem_clear(wr_buf, DFD_UTEST_MAX_RDWR_NUM);
+ len = bpt;
+ if (offset_addr & (bpt - 1)) {
+ page_left = bpt - (offset_addr & (bpt - 1));
+ len = len > page_left ? page_left : len;
+ }
+
+ len = read(fd, wr_buf, len);
+
+ ret = dfd_write_port_i2c(i2c_path, dev_addr, offset_addr, wr_buf, len);
+ if (ret < 0) {
+ break;
+ }
+ offset_addr += len;
+ filesize -= len;
+ }
+
+ close(fd);
+
+ if (ret < 0) {
+ printf("failed ret %d\n", ret);
+ } else {
+ printf("success\n");
+ }
+
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+
+}
+
+/* compare with sys_flie_wr, One more step is read back verification */
+int dfd_utest_sysfs_file_upg(int argc, char* argv[])
+{
+ int ret = 0;
+ uint32_t offset_addr;
+ char *file_name;
+ char *sysfs_loc;
+ char *stopstring;
+ unsigned long filesize;
+ int fd, file_fd;
+ uint8_t wr_buf[DFD_UTEST_MAX_RDWR_NUM];
+ int len, write_len, per_wr_len;
+ int i;
+ uint8_t reread_buf[DFD_UTEST_MAX_RDWR_NUM];
+ int reback_len, reread_len;
+ int j = 0;
+
+ if (argc != 5 && argc != 6) {
+ printf("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_SYSFS_FILE_UPG);
+ goto exit;
+ }
+
+ sysfs_loc = argv[2];
+ offset_addr = strtol(argv[3], &stopstring, 16);
+ file_name = argv[4];
+
+ if (argc == 6) {
+ per_wr_len = strtol(argv[5], &stopstring, 10);
+ if (per_wr_len > DFD_UTEST_MAX_RDWR_NUM || per_wr_len <= 0) {
+ printf("per_wr_byte %d invalid, not in range (0, 256]\n", per_wr_len);
+ goto exit;
+ }
+ } else {
+ per_wr_len = DFD_UTEST_DEFAULT_WR_NUM;
+ }
+ DFD_DEBUG_DBG("per_wr_byte: %d\n", per_wr_len);
+ filesize = dfd_utest_get_file_size(file_name);
+ if (filesize <= 0) {
+ printf("Input invalid file %s, filesize %lu.\n", file_name, filesize);
+ goto exit;
+ }
+
+ fd = open(sysfs_loc, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ printf("open file[%s] fail.\n", sysfs_loc);
+ goto exit;
+ }
+
+ file_fd = open(file_name, O_RDONLY);
+ if (file_fd < 0) {
+ printf("open file[%s] fail.\n", file_name);
+ goto open_dev_err;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ ret = lseek(fd, offset_addr, SEEK_SET);
+ if (ret < 0) {
+ printf("lseek file[%s offset=%d] fail,\n", sysfs_loc, offset_addr);
+ goto fail;
+ }
+
+ printf(":\n");
+ while (filesize > 0) {
+ if (filesize > (unsigned long)per_wr_len) {
+ len = per_wr_len;
+ } else {
+ len = filesize;
+ }
+
+ mem_clear(wr_buf, DFD_UTEST_MAX_RDWR_NUM);
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ len = read(file_fd, wr_buf, len);
+ if (len < 0) {
+ DFD_DEBUG_ERROR("read file[%s] fail, offset = 0x%x retrytimes = %d ret = %d\n",
+ sysfs_loc, offset_addr, i ,len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+ if (i == DFD_I2C_RETRY_TIME) {
+ printf("read file[%s] fail, offset = 0x%x, ret = %d\n", sysfs_loc, offset_addr, len);
+ goto fail;
+ }
+
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ write_len = write(fd, wr_buf, len);
+ if (write_len != len) {
+ DFD_DEBUG_ERROR("write file[%s] fail,offset = 0x%x retrytimes = %d len = %d,write_len =%d\n",
+ sysfs_loc, offset_addr, i ,len, write_len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+ if (i == DFD_I2C_RETRY_TIME) {
+ printf("write file[%s] fail, offset = 0x%x, len = %d,write_len =%d\n",
+ sysfs_loc, offset_addr, len, write_len);
+ goto fail;
+ }
+
+ reback_len = write_len;
+ ret = lseek(fd, -reback_len, SEEK_CUR);
+ if (ret < 0) {
+ printf("reread lseek file[%s offset=%d] fail,lseek len=%d\n",
+ sysfs_loc, offset_addr, reback_len);
+ goto fail;
+ }
+
+ mem_clear(reread_buf, DFD_UTEST_MAX_RDWR_NUM);
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ reread_len = read(fd, reread_buf, reback_len);
+ if (reread_len != reback_len) {
+ DFD_DEBUG_ERROR("reread file[%s] fail,offset = 0x%x retrytimes = %d reread_len = %d,reback_len =%d\n",
+ sysfs_loc, offset_addr, i ,reread_len, reback_len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+ if (i == DFD_I2C_RETRY_TIME) {
+ printf("reread file[%s] fail, offset = 0x%x, reread_len = %d,reback_len = %d\n",
+ sysfs_loc, offset_addr, reread_len, reback_len);
+ goto fail;
+ }
+
+ if (memcmp(reread_buf, wr_buf, reread_len) != 0) {
+ if (j < DFD_I2C_RETRY_TIME) {
+ DFD_DEBUG_ERROR("memcmp file[%s] fail,offset = 0x%x retrytimes = %d\n",
+ sysfs_loc, offset_addr, j);
+ j++;
+ ret = lseek(file_fd, -len, SEEK_CUR);
+ if (ret < 0) {
+ printf("retry file_fd lseek fail,lseek len=%d\n", len);
+ goto fail;
+ }
+ ret = lseek(fd, -write_len, SEEK_CUR);
+ if (ret < 0) {
+ printf("retry fd lseek fail,lseek len=%d\n", write_len);
+ goto fail;
+ }
+ continue;
+ }
+
+ printf("upgrade file[%s] fail, offset = 0x%x.\n", sysfs_loc, offset_addr);
+ printf("want to write buf :\n");
+ for (i = 0; i < reread_len; i++) {
+ printf("0x%x ", wr_buf[i]);
+ }
+ printf("\n");
+
+ printf("actually reread buf :\n");
+ for (i = 0; i < reread_len; i++) {
+ printf("0x%x ", reread_buf[i]);
+ }
+ printf("\n");
+
+ goto fail;
+ }
+
+ offset_addr += len;
+ filesize -= len;
+ usleep(5000);
+ }
+
+ printf("success\n");
+ close(file_fd);
+ close(fd);
+ return DFD_RV_OK;
+
+fail:
+ close(file_fd);
+open_dev_err:
+ close(fd);
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_sysfs_file_wr(int argc, char* argv[])
+{
+ int ret = 0;
+ uint32_t offset_addr;
+ char *file_name;
+ char *sysfs_loc;
+ char *stopstring;
+ unsigned long filesize;
+ int fd, file_fd;
+ uint8_t wr_buf[DFD_UTEST_MAX_RDWR_NUM];
+ int len, write_len, per_wr_len;
+ int i;
+
+ if (argc != 5 && argc != 6) {
+ printf("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_SYSFS_FILE_WR);
+ goto exit;
+ }
+
+ sysfs_loc = argv[2];
+ offset_addr = strtol(argv[3], &stopstring, 16);
+ file_name = argv[4];
+
+ if (argc == 6) {
+ per_wr_len = strtol(argv[5], &stopstring, 10);
+ if (per_wr_len > DFD_UTEST_MAX_RDWR_NUM || per_wr_len <= 0) {
+ printf("per_wr_byte %d invalid, not in range (0, 256]\n", per_wr_len);
+ goto exit;
+ }
+ } else {
+ per_wr_len = DFD_UTEST_DEFAULT_WR_NUM;
+ }
+ DFD_DEBUG_DBG("per_wr_byte: %d\n", per_wr_len);
+ filesize = dfd_utest_get_file_size(file_name);
+ if (filesize <= 0) {
+ printf("Input invalid file %s, filesize %lu.\n", file_name, filesize);
+ goto exit;
+ }
+
+ fd = open(sysfs_loc, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ printf("open file[%s] fail.\n", sysfs_loc);
+ goto exit;
+ }
+
+ file_fd = open(file_name, O_RDONLY);
+ if (file_fd < 0) {
+ printf("open file[%s] fail.\n", file_name);
+ goto open_dev_err;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+
+ ret = lseek(fd, offset_addr, SEEK_SET);
+ if (ret < 0) {
+ printf("lseek file[%s offset=%d] fail,\n", sysfs_loc, offset_addr);
+ goto fail;
+ }
+
+ printf(":\n");
+ while (filesize > 0) {
+ if (filesize > (unsigned long)per_wr_len) {
+ len = per_wr_len;
+ } else {
+ len = filesize;
+ }
+
+ mem_clear(wr_buf, DFD_UTEST_MAX_RDWR_NUM);
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ len = read(file_fd, wr_buf, len);
+ if (len < 0) {
+ DFD_DEBUG_ERROR("read file[%s] fail, offset = 0x%x retrytimes = %d ret = %d\n",
+ sysfs_loc, offset_addr, i ,len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+ if (i == DFD_I2C_RETRY_TIME) {
+ printf("read file[%s] fail, offset = 0x%x, ret = %d\n", sysfs_loc, offset_addr, len);
+ goto fail;
+ }
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ write_len = write(fd, wr_buf, len);
+ if (write_len != len) {
+ DFD_DEBUG_ERROR("write file[%s] fail,offset = 0x%x retrytimes = %d len = %d,write_len =%d\n", sysfs_loc, offset_addr, i ,len, write_len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ break;
+ }
+
+ if(i == DFD_I2C_RETRY_TIME) {
+ printf("write file[%s] fail, offset = 0x%x, len = %d,write_len =%d\n", sysfs_loc, offset_addr, len, write_len);
+ ret = -1;
+ goto fail;
+ }
+ offset_addr += len;
+ filesize -= len;
+ usleep(5000);
+ }
+
+ printf("success\n");
+ close(file_fd);
+ close(fd);
+ return DFD_RV_OK;
+
+fail:
+ close(file_fd);
+open_dev_err:
+ close(fd);
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_sysfs_file_rd(int argc, char* argv[])
+{
+ int ret = 0;
+ uint32_t offset_addr;
+ char *sysfs_loc;
+ char *stopstring;
+ int fd;
+ uint8_t rd_buf[DFD_UTEST_MAX_RDWR_NUM];
+ int len, read_len;;
+
+ if (argc != 5) {
+ printf("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_SYSFS_FILE_RD);
+ goto exit;
+ }
+
+ sysfs_loc = argv[2];
+ offset_addr = strtol(argv[3], &stopstring, 16);
+ len = strtol(argv[4], &stopstring, 10);
+
+ if (len > DFD_UTEST_MAX_RDWR_NUM) {
+ printf("Input num %d exceed max 256.\n", len);
+ goto exit;
+ }
+
+ fd = open(sysfs_loc, O_RDONLY);
+ if (fd < 0) {
+ printf("open file[%s] fail.\n", sysfs_loc);
+ goto exit;
+ }
+ dfd_utest_print_cmd(argc, argv);
+
+ printf(":\n");
+
+ ret = lseek(fd, offset_addr, SEEK_SET);
+ if (ret < 0) {
+ printf("lseek failed ret %d.\n", ret);
+ goto fail;
+ }
+
+ mem_clear(rd_buf, DFD_UTEST_MAX_RDWR_NUM);
+ read_len = read(fd, rd_buf, len);
+ if (read_len != len) {
+ printf("read failed read_len %d len %d.\n", read_len, len);
+ goto fail;
+ }
+ dfd_utest_printf_reg(rd_buf, read_len, offset_addr);
+ close(fd);
+ return DFD_RV_OK;
+
+fail:
+ close(fd);
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_msr_rd(int argc, char* argv[])
+{
+ int fd;
+ char msr_file_name[64];
+ uint64_t data;
+ uint64_t read_result;
+ char *stopstring;
+ uint8_t cpu_index, width;
+ uint64_t offset;
+
+ if (argc != 5) {
+ printf("rdmsr failed: Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_MSR_RD);
+ goto exit;
+ }
+
+ cpu_index = strtol(argv[2], &stopstring, 10);
+ offset = strtol(argv[3], &stopstring, 16);
+ width = strtol(argv[4], &stopstring, 10);
+
+ if (width != 8 && width != 16 && width != 32 && width != 64) {
+ printf("rdmsr failed: width:%u Input invalid.only support 8 16 32 64\n", width);
+ goto exit;
+ }
+
+ mem_clear(msr_file_name, sizeof(msr_file_name));
+ sprintf(msr_file_name, "/dev/cpu/%u/msr", cpu_index);
+
+ fd = open(msr_file_name, O_RDONLY);
+ if (fd < 0) {
+ if (errno == ENXIO) {
+ fprintf(stderr, "rdmsr failed: No CPU %u\n", cpu_index);
+ } else if (errno == EIO) {
+ fprintf(stderr, "rdmsr failed: CPU %u doesn't support MSRs\n", cpu_index);
+ } else if (errno == ENOENT) {
+ fprintf(stderr, "rdmsr failed: can't find %s file, Please check if modprobe msr driver already\n", msr_file_name);
+ } else {
+ printf("rdmsr failed: %s open failed. errno:%d\n", msr_file_name, errno);
+ }
+ goto exit;
+ }
+
+ if (pread(fd, &data, sizeof(data), offset) != sizeof(data)) {
+ fprintf(stderr, "rdmsr failed: CPU:%u offset:0x%lx read failed\n", cpu_index, offset);
+ goto fail;
+ }
+
+ switch (width) {
+ case 8:
+ read_result = (volatile uint8_t)data;
+ break;
+ case 16:
+ read_result = (volatile uint16_t)data;
+ break;
+ case 32:
+ read_result = (volatile uint32_t)data;
+ break;
+ case 64:
+ read_result = (volatile uint64_t)data;
+ break;
+ default:
+ printf("rdmsr failed: width:%u illegal width.\n", width);
+ goto fail;
+ }
+
+ printf("0x%lx\n", read_result);
+ close(fd);
+ return DFD_RV_OK;
+
+fail:
+ close(fd);
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+int dfd_utest_sysfs_data_wr(int argc, char* argv[])
+{
+ uint32_t offset;
+ char *sysfs_loc;
+ char *stopstring;
+ uint8_t wr_buf[DFD_UTEST_MAX_RDWR_NUM];
+ int ret, i;
+ int fd, len, write_len, index;
+
+ if (argc < 5) {
+ DFD_DEBUG_ERROR("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_SYSFS_DATA_WR);
+ goto exit;
+ }
+
+ dfd_utest_print_cmd(argc, argv);
+ printf(":\n");
+
+ sysfs_loc = argv[2];
+ offset = strtol(argv[3], &stopstring, 16);
+ len = argc - 4;
+ mem_clear(wr_buf, sizeof(wr_buf));
+ for (i = 0; i < len; i++) {
+ wr_buf[i] = strtol(argv[4 + i], &stopstring, 16);
+ DFD_DEBUG_DBG("index :%d value %x\n", i , wr_buf[i]);
+ }
+
+ fd = open(sysfs_loc, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ printf("open file[%s] fail.\n", sysfs_loc);
+ goto exit;
+ }
+
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret < 0) {
+ printf("lseek file[%s offset=%d] fail,\n", sysfs_loc, offset);
+ goto fail;
+ }
+ index = 0;
+ while (len > 0) {
+ for (i = 0; i < DFD_I2C_RETRY_TIME; i++) {
+ write_len = write(fd, &wr_buf[index], len);
+ if (write_len < 0) {
+ DFD_DEBUG_ERROR("write file[%s] fail, retrytimes: %d, offset: 0x%x, len: %d, write_len: %d\n",
+ sysfs_loc, offset, i, len, write_len);
+ usleep(DFD_I2C_RETRY_SLEEP_TIME);
+ continue;
+ }
+ if (write_len == 0) {
+ DFD_DEBUG_ERROR("write file[%s] EOF, offset: 0x%x, len: %d, write_len: %d\n",
+ sysfs_loc, offset, len, write_len);
+ goto fail;
+ }
+ break;
+ }
+ if(i == DFD_I2C_RETRY_TIME) {
+ printf("write file[%s] fail, offset: 0x%x, len: %d, write_len: %d\n",
+ sysfs_loc, offset, len, write_len);
+ goto fail;
+ }
+ offset += write_len;
+ index += write_len;
+ len -= write_len;
+ usleep(5000);
+ }
+ printf("success\n");
+ close(fd);
+ return DFD_RV_OK;
+fail:
+ close(fd);
+exit:
+ return DFD_RV_MODE_NOTSUPPORT;
+}
+
+static void phy_help(char *name)
+{
+ fprintf(stderr,
+ "Usage: %s phy_index(dec) regnum(hex) [regval(hex)] \n"
+ " phy_index phydev index \n"
+ " regnum phydev register address \n"
+ " regval phydev register value \n",
+ name);
+ return;
+}
+
+static void mdio_help(char *name)
+{
+ fprintf(stderr,
+ "Usage: %s mdio_index(dec) phyaddr(hex) regnum(hex) [regval(hex)] \n"
+ " mdio_index mdiodev index \n"
+ " phyaddr phydev address \n"
+ " regnum phydev register address \n"
+ " regval phydev register value \n",
+ name);
+ return;
+}
+
+static int phydev_arg_parse(int argc, char* argv[], int *phy_index, uint32_t *regnum, uint32_t *regval,
+ int num_arg)
+{
+
+ unsigned long index, regaddr, value;
+ char *end;
+
+ if (argc != num_arg) {
+ return -EINVAL;
+ }
+
+ index = strtoul(argv[2], &end, 0);
+ if (*end) {
+ fprintf(stderr, "Error: index invalid!\n");
+ return -EINVAL;
+ }
+
+ regaddr = strtoul(argv[3], &end, 0);
+ if (*end || regaddr > 0xffff) {
+ fprintf(stderr, "Error: regaddr invalid!\n");
+ return -EINVAL;
+ }
+
+ if (argc > 4) {
+ value = strtoul(argv[4], &end, 0);
+ if (*end || value > 0xffff) {
+ fprintf(stderr, "Error: reg data invalid!\n");
+ return -EINVAL;
+ }
+
+ *regval = (uint32_t)value;
+ }
+
+ *phy_index = (uint32_t)index;
+ *regnum = (uint32_t)regaddr;
+
+ return 0;
+}
+
+static int mdiodev_arg_parse(int argc, char* argv[], int *mdio_index, int *phyaddr, uint32_t *regnum,
+ uint32_t *regval, int num_arg)
+{
+
+ unsigned long index, addr, regaddr, value;
+ char *end;
+
+ if (argc != num_arg) {
+ return -EINVAL;
+ }
+
+ index = strtoul(argv[2], &end, 0);
+ if (*end) {
+ fprintf(stderr, "Error: index invalid!\n");
+ return -EINVAL;
+ }
+
+ addr = strtoul(argv[3], &end, 0);
+ if (*end || addr > 0x1f) {
+ fprintf(stderr, "Error: phyaddr invalid!\n");
+ return -EINVAL;
+ }
+
+ regaddr = strtoul(argv[4], &end, 0);
+ if (*end || regaddr > 0xffff) {
+ fprintf(stderr, "Error: regaddr invalid!\n");
+ return -EINVAL;
+ }
+
+ if (argc > 5) {
+ value = strtoul(argv[5], &end, 0);
+ if (*end || value > 0xffff) {
+ fprintf(stderr, "Error: reg data invalid!\n");
+ return -EINVAL;
+ }
+
+ *regval = (uint32_t)value;
+ }
+
+ *mdio_index = (uint32_t)index;
+ *phyaddr = (int)addr;
+ *regnum = (uint32_t)regaddr;
+
+ return 0;
+}
+
+int dfd_utest_phydev_list(int argc, char* argv[])
+{
+ int fd;
+
+ if (argc != 2) {
+ printf("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_PHYDEV_LIST);
+ return DFD_RV_MODE_NOTSUPPORT;
+ }
+
+ argv = argv;
+ fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (fd < 0) {
+ fprintf(stderr, "Error: Could not open file "
+ "/dev/dram: %s\n", strerror(errno));
+ return -1;
+ }
+
+ (void)ioctl(fd, CMD_PHY_LIST, NULL);
+
+ close(fd);
+
+ return 0;
+}
+
+int dfd_utest_phydev_rd(int argc, char* argv[])
+{
+ struct phydev_user_info phy_info;
+ int fd;
+ long int ret;
+
+ ret = phydev_arg_parse(argc, argv, &phy_info.phy_index, &phy_info.regnum, &phy_info.regval, 4);
+ if (ret < 0) {
+ phy_help("phydev_rd");
+ return -1;
+ }
+
+ fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (fd < 0) {
+ fprintf(stderr, "Error: Could not open file "
+ "/dev/dram: %s\n", strerror(errno));
+ return -1;
+ }
+
+ ret = ioctl(fd, CMD_PHY_READ, &phy_info);
+ if (ret < 0) {
+ fprintf(stderr, "Error: phy read error : %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ printf("Read success --- phydev%d regnum: 0x%x, value: 0x%x\n",phy_info.phy_index,
+ phy_info.regnum, phy_info.regval);
+
+ return 0;
+}
+
+int dfd_utest_phydev_wr(int argc, char* argv[])
+{
+ struct phydev_user_info phy_info;
+ int fd;
+ long int ret;
+
+ ret = phydev_arg_parse(argc, argv, &phy_info.phy_index, &phy_info.regnum, &phy_info.regval, 5);
+ if (ret < 0) {
+ phy_help("phydev_wr");
+ return -1;
+ }
+
+ fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (fd < 0) {
+ fprintf(stderr, "Error: Could not open file "
+ "/dev/dram: %s\n", strerror(errno));
+ return -1;
+ }
+
+ ret = ioctl(fd, CMD_PHY_WRITE, &phy_info);
+ if (ret < 0) {
+ fprintf(stderr, "Error: phy write error : %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ printf("write success --- phydev%d regnum: 0x%x, value: 0x%x\n",phy_info.phy_index,
+ phy_info.regnum, phy_info.regval);
+
+ return 0;
+}
+
+int dfd_utest_mdiodev_list(int argc, char* argv[])
+{
+ int fd;
+
+ if (argc != 2) {
+ printf("Input invalid.\n");
+ dfd_utest_printf_single_help(DFD_UTEST_ITEM_MDIODEV_LIST);
+ return DFD_RV_MODE_NOTSUPPORT;
+ }
+
+ argv = argv;
+ fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (fd < 0) {
+ fprintf(stderr, "Error: Could not open file "
+ "/dev/dram: %s\n", strerror(errno));
+ return -1;
+ }
+
+ (void)ioctl(fd, CMD_MDIO_LIST, NULL);
+
+ close(fd);
+
+ return 0;
+}
+
+int dfd_utest_mdiodev_rd(int argc, char* argv[])
+{
+ struct mdio_dev_user_info mdio_info;
+ int fd;
+ long int ret;
+
+ ret = mdiodev_arg_parse(argc, argv, &mdio_info.mdio_index, &mdio_info.phyaddr,
+ &mdio_info.regnum, &mdio_info.regval, 5);
+ if (ret < 0) {
+ mdio_help("mdiodev_rd");
+ return -1;
+ }
+
+ fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (fd < 0) {
+ fprintf(stderr, "Error: Could not open file "
+ "/dev/dram: %s\n", strerror(errno));
+ return -1;
+ }
+
+ ret = ioctl(fd, CMD_MDIO_READ, &mdio_info);
+ if (ret < 0) {
+ fprintf(stderr, "Error: mdio read error : %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ printf("Read success\n mdio_index phyaddr regnum value\n");
+ printf(" %-10d %#-10x %#-10x %#-10x\n", mdio_info.mdio_index, mdio_info.phyaddr,
+ mdio_info.regnum, mdio_info.regval);
+
+ return 0;
+}
+
+int dfd_utest_mdiodev_wr(int argc, char* argv[])
+{
+ struct mdio_dev_user_info mdio_info;
+ int fd;
+ long int ret;
+
+ ret = mdiodev_arg_parse(argc, argv, &mdio_info.mdio_index, &mdio_info.phyaddr,
+ &mdio_info.regnum, &mdio_info.regval, 6);
+ if (ret < 0) {
+ mdio_help("mdiodev_wr");
+ return -1;
+ }
+
+ fd = open("/dev/dram_test", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ if (fd < 0) {
+ fprintf(stderr, "Error: Could not open file "
+ "/dev/dram: %s\n", strerror(errno));
+ return -1;
+ }
+
+ ret = ioctl(fd, CMD_MDIO_WRITE, &mdio_info);
+ if (ret < 0) {
+ fprintf(stderr, "Error: mdio write error : %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ printf("write success\n mdio_index phyaddr regnum value\n");
+ printf(" %-10d %#-10x %#-10x %#-10x\n", mdio_info.mdio_index, mdio_info.phyaddr,
+ mdio_info.regnum, mdio_info.regval);
+
+ return 0;
+}
+
+dfd_utest_proc_fun dfd_utest_get_proc_func(char *type_str)
+{
+ int i, tbl_size;
+
+ tbl_size = sizeof(g_dfd_unit_test) / sizeof(g_dfd_unit_test[0]);
+
+ for (i = 0; i < tbl_size; i++) {
+ if (!strncmp(g_dfd_unit_test[i].type_str, type_str, strlen(g_dfd_unit_test[i].type_str))) {
+ return g_dfd_unit_test[i].utest_func;
+ }
+ }
+ DFD_DEBUG_DBG("type: %s not match.\n", type_str);
+ return NULL;
+}
+
+void dfd_utest_cmd_main(int argc, char* argv[])
+{
+ dfd_utest_proc_fun pfunc;
+ int ret;
+
+ if (argc < 2) {
+ dfd_utest_print_all_help();
+ return;
+ }
+
+ pfunc = dfd_utest_get_proc_func(argv[1]);
+ if (pfunc == NULL) {
+ DFD_DEBUG_DBG("utest type %s in not support.\n", argv[1]);
+ dfd_utest_print_all_help();
+ return;
+ }
+ ret = pfunc(argc, argv);
+ if ((ret != DFD_RV_MODE_NOTSUPPORT) && (ret != DFD_RV_INDEX_INVALID)) {
+ if (ret == DFD_RV_OK) {
+ DFD_DEBUG_DBG(" [SUCCESS]\n");
+ } else {
+ DFD_DEBUG_DBG(" [FAIL(%d)]\n", ret);
+ }
+ }
+
+ return;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_utest.h b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_utest.h
new file mode 100644
index 000000000000..1ae65148ea9c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/dev_util/dfd_utest.h
@@ -0,0 +1,109 @@
+/* monitor_utest.h */
+#ifndef __DFD_UTEST_H__
+#define __DFD_UTEST_H__
+
+#include
+
+extern int g_dfd_debug_sw;
+extern int g_dfd_debugpp_sw;
+
+#define DFD_UTEST_TRUE_FALSE_STRING(flag) ((flag == true) ? "true" : "false")
+
+#define DFD_DEBUG_DBG(fmt, args...) do { \
+ if (g_dfd_debug_sw) { \
+ printf("" fmt,\
+ ##args); \
+ } \
+} while (0)
+
+#define DFD_DEBUG_ERROR(fmt, args...) do { \
+ if (g_dfd_debugpp_sw) { \
+ printf("" fmt,\
+ ##args); \
+ } \
+} while (0)
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+typedef enum dfd_rv_s {
+ DFD_RV_OK = 0,
+ DFD_RV_INIT_ERR = 1,
+ DFD_RV_SLOT_INVALID = 2,
+ DFD_RV_MODE_INVALID = 3,
+ DFD_RV_MODE_NOTSUPPORT = 4,
+ DFD_RV_TYPE_ERR = 5,
+ DFD_RV_DEV_NOTSUPPORT = 6,
+ DFD_RV_DEV_FAIL = 7,
+ DFD_RV_INDEX_INVALID = 8,
+ DFD_RV_NO_INTF = 9,
+ DFD_RV_NO_NODE = 10,
+ DFD_RV_NODE_FAIL = 11,
+} dfd_rv_t;
+
+#define DFD_DEBUG_BUF_LEN (32)
+#define DFD_DEBUGP_DEBUG_FILE "/sbin/.dfd_debugp_flag"
+#define DFD_DEBUGPP_DEBUG_FILE "/sbin/.dfd_debugpp_flag"
+
+#define DFD_UTEST_MAX_PARA_NUM (4)
+#define DFD_UTEST_TYPE_STRING_LEN (64)
+#define DFD_UTEST_MATCH_STRING_LEN (64)
+#define DFD_UTEST_HELP_STRING_LEN (256)
+#define DFD_UTEST_INVALID_PARA (-1)
+#define DFD_UTEST_BUFF_LEN (64)
+
+typedef enum dfd_fpga_cpld_flag_e {
+ DFD_CPLD_RW_FLAG = 0x00,
+ DFD_FPGA_RW_FLAG = 0x01,
+} dfd_fpga_cpld_flag_t;
+
+typedef int (* dfd_utest_proc_fun)(int argc, char* argv[]);
+
+#define DFD_UTEST_ITEM_ALL \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_RD, i2c_rd, "i2c_rd [i2c_bus] [slave_addr] [offset] [len]", "i2c_rd [i2c_bus] [slave_addr] [offset] [len]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_WR, i2c_wr, "i2c_wr [i2c_bus] [slave_addr] [offset] [data0] ... [dataN]", "i2c_wr [i2c_bus] [slave_addr] [offset] [data0] ... [dataN]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_IO_RD, io_rd, "io_rd [offset] [len]", "io_rd [offset] [len]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_IO_WR, io_wr, "io_wr [offset] [data0]... [dataN]", "io_wr [offset] [data0]... [dataN]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_PHYMEM_RD, phymem_rd, "phymem_rd [bit_width] [offset] [len]", "phymem_rd [bit_width] [offset] [len]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_PHYMEM_WR, phymem_wr, "phymem_wr [bit_width] [offset] [data0]... [dataN]", "phymem_wr [bit_width] [offset] [data0]... [dataN]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_KMEM_RD, kmem_rd, "kmem_rd [bit_width] [offset] [len]", "kmem_rd [bit_width] [offset] [len]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_KMEM_WR, kmem_wr, "kmem_wr [bit_width][offset] [data0]... [dataN]", "kmem_wr [bit_width] [offset] [data0]... [dataN]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_FILE_WR, i2c_file_wr, "i2c_file_wr [i2c_bus] [slave_addr] [offset] [bpt] [filename]", "i2c_file_wr [i2c_bus] [slave_addr] [offset] [bpt] [filename]\nbpt:bytes per times") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_SYSFS_FILE_WR, sysfs_file_wr, "sysfs_file_wr [sysfs_loc] [offset] [filename] [per_wr_byte]", "sysfs_file_wr [sysfs_loc] [offset] [filename] [per_wr_byte]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_SYSFS_FILE_RD, sysfs_file_rd, "sysfs_file_rd [sysfs_loc] [offset] [len]", "sysfs_file_rd [sysfs_loc] [offset] [len]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_SYSFS_FILE_UPG, sysfs_file_upg, "sysfs_file_upg [sysfs_loc] [offset] [filename] [per_wr_byte]", "sysfs_file_upg [sysfs_loc] [offset] [filename] [per_wr_byte]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_GEN_RD, i2c_gen_rd, "i2c_gen_rd [i2c_bus] [slave_addr] [addr_bitwidth] [offset] [data_bitwidth] [len]", "i2c_gen_rd [i2c_bus] [slave_addr] [addr_bitwidth] [offset] [data_bitwidth] [len]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_I2C_GEN_WR, i2c_gen_wr, "i2c_gen_wr [i2c_bus] [slave_addr] [addr_bitwidth] [offset] [data_bitwidth] [data0]... [dataN]", "i2c_gen_wr [i2c_bus] [slave_addr] [addr_bitwidth] [offset] [data_bitwidth] [data0]... [dataN]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_MSR_RD, msr_rd, "msr_rd [cpu_index] [offset] [width]", "msr_rd [cpu_index] [offset] [width]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_SYSFS_DATA_WR, sysfs_data_wr, "sysfs_data_wr [sysfs_loc] [offset] [data0] ... [dataN]", "sysfs_data_wr [sysfs_loc] [offset] [data0] ... [dataN]]") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_PHYDEV_LIST, phydev_list, "phydev_list", "phydev_list") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_PHYDEV_RD, phydev_rd, "phydev_rd phy_index reg_addr", "phydev_rd phy_index reg_addr") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_PHYDEV_WR, phydev_wr, "phydev_wr phy_index reg_addr reg_data", "phydev_wr phy_index reg_addr reg_data") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_MDIODEV_LIST, mdiodev_list, "mdiodev_list", "mdiodev_list") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_MDIODEV_RD, mdiodev_rd, "mdiodev_rd mdio_index phyaddr reg_addr", "mdiodev_rd mdio_index phyaddr reg_addr") \
+ DFD_UTEST_ITEM(DFD_UTEST_ITEM_MDIODEV_WR, mdiodev_wr, "mdiodev_wr mdio_index phyaddr reg_addr reg_data", "mdiodev_wr mdio_index phyaddr reg_addr reg_data") \
+
+#ifdef DFD_UTEST_ITEM
+#undef DFD_UTEST_ITEM
+#endif
+#define DFD_UTEST_ITEM(_id, _type_str, _help_info, _help_info_detail) _id,
+typedef enum dfd_utest_item_id_s {
+ DFD_UTEST_ITEM_ALL
+} dfd_utest_item_id_t;
+
+typedef struct {
+ int utest_type;
+ char type_str[DFD_UTEST_TYPE_STRING_LEN];
+ dfd_utest_proc_fun utest_func;
+ char help_info[DFD_UTEST_HELP_STRING_LEN];
+ char help_info_detail[DFD_UTEST_HELP_STRING_LEN];
+} dfd_utest_t;
+
+void dfd_utest_cmd_main(int argc, char* argv[]);
+
+#ifdef DFD_UTEST_ITEM
+#undef DFD_UTEST_ITEM
+#endif
+#define DFD_UTEST_ITEM(_id, _type_str, _help_info, _help_info_detail) int dfd_utest_##_type_str(int argc, char* argv[]);
+DFD_UTEST_ITEM_ALL
+
+#endif
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/Makefile
new file mode 100644
index 000000000000..1701b5f62114
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/Makefile
@@ -0,0 +1,18 @@
+top_srcdir:=$(shell pwd)
+include $(top_srcdir)/Rules.mk
+
+firmware-y:=
+firmware-y += fw_upgrade
+
+.PHONY: all
+all: build
+
+.PHONY: build
+build: $(firmware-y)
+$(foreach dir,$(firmware-y),$(eval $(call compile_dirs,$(dir))))
+
+.PHONY: rpmpkg
+rpmpkg:
+ifeq ("$(CONFIG_CPLD_UPGRADE_ISPVME)", "y")
+ #$(RPMPKG) $(install_cpld_dir) firmware-cpld-ispvme.spec git
+endif
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/Rules.mk b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/Rules.mk
new file mode 100644
index 000000000000..5fb5a09d34fd
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/Rules.mk
@@ -0,0 +1,42 @@
+CC ?= $(CROSS)gcc
+AR ?= $(CROSS)ar
+AS ?= $(CROSS)as
+LD ?= $(CROSS)ld
+STRIP ?= $(CROSS)strip
+
+install_root:=${top_srcdir}/images
+
+install_header_dir:=${install_root}/header
+install_adir:=$(install_root)/lib
+install_symbol_dir:=$(install_root)/symbol
+symbol_files:=$(shell find $(EXPORT_SYMBOL) -name 'Module.symvers')
+#
+# symbol_files += $(shell find $(install_symbol_dir) -name 'Module.symvers')
+# KBUILD_EXTRA_SYMBOLS += $(symbol_files)
+# export KBUILD_EXTRA_SYMBOLS
+
+# top root: install_rootfs_dir
+install_rootfs_dir:=$(install_root)/rootfs
+
+install_sodir:=$(install_rootfs_dir)/$(INSTALL_SODIR)
+
+install_usr_bin_dir:=$(install_rootfs_dir)/usr/bin
+install_sbin_dir:=$(install_rootfs_dir)/sbin
+install_etc_dir:=$(install_rootfs_dir)/etc
+
+export INSTALL_MOD_PATH:=$(ROOT)
+
+BUILD_CFLAGS:=$(CFLAGS) -I$(install_header_dir)
+BUILD_LDFLAGS:=$(LDFLAGS) -L/$(install_sodir) -L/$(install_adir)
+
+define compile_dirs
+.PHONY: $(1)
+$(1):
+ @echo;echo "building $(1)..."
+ @$(MAKE) -C ${1}
+endef
+
+compile.c = $(CC) $(BUILD_CFLAGS) -d -c -o $@ $<
+%.o: %.c
+ $(compile.c)
+
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/Makefile
new file mode 100644
index 000000000000..8b4bca739087
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/Makefile
@@ -0,0 +1,39 @@
+include ../Rules.mk
+
+OBJ = fw_upgrade.o fw_upgrade_debug.o
+
+LIB += $(BUILD_CFALGS) $(BUILD_LDFLAGS) -lpthread
+ifdef ENABLE_GCOV
+ifeq ($(ENABLE_GCOV), y)
+LIB += -fprofile-arcs
+endif
+endif # ENABLE_GCOV
+
+APP = fw_upgrade
+BUILD_DIR = tmp
+ELF_FILE = $(BUILD_DIR)/$(APP)
+MAP_FILE = $(BUILD_DIR)/$(APP).map.sym
+INCLUDE = -Iinclude
+CFLAGS+=-Wall -W -g
+
+.PHONY: build
+build:make-dir $(addprefix $(BUILD_DIR)/,$(OBJ))
+ $(CC) -o $(ELF_FILE) $(addprefix $(BUILD_DIR)/,$(OBJ)) $(LINKFLAGS) $(LIB)
+
+ cp -p $(ELF_FILE) $(common_out_put_dir)
+
+.PHONY: make-dir
+make-dir:
+ @mkdir -p $(BUILD_DIR)
+
+$(BUILD_DIR)/%.o:%.c
+ $(CC) -c $(CFLAGS) $(INCLUDE) $< -o $@
+
+.PHONY: install
+install:
+ echo "fw_upgrade install success."
+ cp -p $(ELF_FILE) $(common_out_put_dir)
+
+.PHONY: clean
+clean:
+ rm -rf $(BUILD_DIR)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/fw_upgrade.c b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/fw_upgrade.c
new file mode 100644
index 000000000000..2045608d5c3b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/fw_upgrade.c
@@ -0,0 +1,1632 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "fw_upgrade.h"
+
+static flash_info_t flash_info[] = {
+ {
+ .flash_name = "M25L6433F",
+ .flash_size = M32,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = MX25L6433F,
+ .block_size = STEP_64,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "S25FL512S",
+ .flash_size = M64,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = S25FL512S,
+ .block_size = STEP_256,
+ .full_erase = 0,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "MX25l512",
+ .flash_size = M64,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = MX25l512,
+ .block_size = STEP_64,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "STM25P64",
+ .flash_size = M12,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = STM25P64,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "STM25P128",
+ .flash_size = M16,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = STM25P128,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "N25Q256",
+ .flash_size = M16,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = N25Q256,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "N25Q512",
+ .flash_size = M16,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = N25Q512,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "W25X16",
+ .flash_size = M3,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = W25X16,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "W25X64",
+ .flash_size = M12,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = W25X64,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "W25Q64BV",
+ .flash_size = M12,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = W25Q64BV,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "W25Q128BV",
+ .flash_size = M16,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = W25Q128BV,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "W25Q256FV",
+ .flash_size = M16,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = W25Q256FV,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "MX25L1605D",
+ .flash_size = M32,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = MX25L1605D,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "MX25L12805D",
+ .flash_size = M32,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = MX25L12805D,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "MX66L1G45G",
+ .flash_size = M128,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = MX66L1G45G,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+ {
+ .flash_name = "GD25Q256",
+ .flash_size = M16,
+ .flash_type = SPI,
+ .page_size = BYTE_256,
+ .flash_id = GD25Q256,
+ .block_size = STEP_256,
+ .full_erase = 1,
+ .erase_block_command = BLOCK_ERASE_64,
+ .page_program = COMMON_PAGE_PROGRAM,
+ },
+};
+
+static int debug_on;
+
+static void help(void)
+{
+ printf("------------------------------BMC Upgrade Tool--------------------------------\n");
+ printf("Program Flash:\n");
+ printf("\tfw_upgrade upgrade [file name] [chip select: 0 | 1 | 2] ");
+ printf("[erase type: full | block]\n");
+ printf("\t[file name] if file is not located at /home/admin, path should be added\n");
+ printf("\t[chip select] 0:master, 1:slave, 2:both\n");
+ printf("\t[erase type] choose a way to erase chip, full erase would be faster\n");
+ printf("Read BMC Reg:\n");
+ printf("\tfw_upgrade rd [address] [length]\n");
+ printf("\t[address(Hexadecimal)] register address of BMC\n");
+ printf("\t[length(decimal)] length of read data, should be times of 4\n");
+
+ return;
+}
+
+static int set_ioport_rw_access(void)
+{
+
+ if ( iopl(3) < 0) {
+ printf("Can't get access to /dev/port \n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int get_file_size(char *file_name)
+{
+ FILE * pFile;
+ int size;
+
+ pFile = fopen(file_name,"rb");
+ if (pFile == NULL) {
+ printf("Error opening file\n");
+ return -1;
+ }
+ fseek (pFile, 0, SEEK_END);
+ size = ftell(pFile);
+ fclose (pFile);
+ return size;
+}
+
+static uint8_t _read(uint16_t addr)
+{
+ return inb(addr);
+}
+
+static void _write(uint16_t addr, uint8_t val)
+{
+ outb(val, addr);
+
+ return;
+}
+
+static void write_addr_port(uint8_t addr_val, uint16_t addr_port)
+{
+ _write(addr_port, addr_val);
+
+ return;
+}
+
+static void write_data_port(uint8_t val, uint16_t data_port)
+{
+ _write(data_port, val);
+
+ return;
+}
+
+static uint8_t read_data_port(uint16_t data_port)
+{
+ return _read(data_port);
+}
+
+static void write_ilpc2ahb_addr(uint32_t addr)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ write_addr_port(SUPERIO_REG0 + i, LPC_ADDR_PORT);
+ write_data_port((addr >> (8 * (3 - i))) & MASK, LPC_DATA_PORT);
+ }
+
+ return;
+}
+
+static void write_ilpc2ahb_data(uint32_t data)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ write_addr_port(SUPERIO_REG4 + i, LPC_ADDR_PORT);
+ write_data_port((data >> (8 * (3 - i))) & MASK, LPC_DATA_PORT);
+ }
+
+ return;
+}
+
+static uint32_t read_ilpc2ahb_data(void)
+{
+ int i, tmp;
+ uint32_t res;
+
+ res = 0;
+ for (i = 0; i < 4; i++) {
+ write_addr_port(SUPERIO_REG4 + i, LPC_ADDR_PORT);
+ tmp = read_data_port(LPC_DATA_PORT);
+ res |= (tmp << (8 * (3 - i)));
+ }
+
+ return res;
+}
+
+static void trigger_ilpc2ahb_read(void)
+{
+ write_addr_port(SUPERIO_FE, LPC_ADDR_PORT);
+ read_data_port(LPC_DATA_PORT);
+
+ return;
+}
+
+static void trigger_ilpc2ahb_write(void)
+{
+ write_addr_port(SUPERIO_FE, LPC_ADDR_PORT);
+ write_data_port(TOGGLE_WRITE, LPC_DATA_PORT);
+
+ return;
+}
+
+static uint32_t read_bmc_reg(uint32_t addr)
+{
+ uint32_t res;
+
+ write_ilpc2ahb_addr(addr);
+ trigger_ilpc2ahb_read();
+ res = read_ilpc2ahb_data();
+
+ return res;
+}
+
+static void write_bmc_reg(uint32_t addr, uint32_t val)
+{
+ write_ilpc2ahb_addr(addr);
+ write_ilpc2ahb_data(val);
+ trigger_ilpc2ahb_write();
+
+ return;
+}
+
+static uint32_t read_bmc_flash_data(void)
+{
+ uint32_t res;
+
+ trigger_ilpc2ahb_read();
+ res = read_ilpc2ahb_data();
+
+ return res;
+}
+
+static void write_bmc_flash_data(uint32_t data)
+{
+ write_ilpc2ahb_data(data);
+ trigger_ilpc2ahb_write();
+
+ return;
+}
+
+static void write_bmc_flash_addr(uint32_t addr)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ write_addr_port(SUPERIO_REG4 + i, LPC_ADDR_PORT);
+ write_data_port((addr >> (8 * i)) & MASK, LPC_DATA_PORT);
+ }
+
+ trigger_ilpc2ahb_write();
+
+ return;
+}
+
+static void enable_bytes(int byte)
+{
+ write_addr_port(SUPERIO_REG8, LPC_ADDR_PORT);
+ switch (byte) {
+ case BYTE1:
+ write_data_port(SUPERIO_A0 + BYTE1_VAL, LPC_DATA_PORT);
+ break;
+ case BYTE2:
+ write_data_port(SUPERIO_A0 + BYTE2_VAL, LPC_DATA_PORT);
+ break;
+ case BYTE4:
+ write_data_port(SUPERIO_A0 + BYTE4_VAL, LPC_DATA_PORT);
+ break;
+ default:
+ write_data_port(SUPERIO_A0 + BYTE_RESERVED, LPC_DATA_PORT);
+ break;
+ }
+
+ return;
+}
+
+static void pull_ce_down(flash_info_t* info)
+{
+ write_bmc_reg(info->ce_control_reg, USER_MODE_PULL_CE_DOWN);
+
+ return;
+}
+
+static void pull_ce_up(flash_info_t* info)
+{
+ write_bmc_reg(info->ce_control_reg, USER_MODE_PULL_CE_UP);
+
+ return;
+}
+
+static void send_cmd(uint32_t flash_base_addr, int cmd)
+{
+ write_ilpc2ahb_addr(flash_base_addr);
+ enable_bytes(1);
+ write_addr_port(SUPERIO_REG7, LPC_ADDR_PORT);
+ write_data_port(cmd & MASK, LPC_DATA_PORT);
+ trigger_ilpc2ahb_write();
+ enable_bytes(4);
+
+ return;
+}
+
+static void send_cmd_to_flash(flash_info_t* info, int cmd)
+{
+ pull_ce_down(info);
+ send_cmd(info->flash_base_addr, cmd);
+ pull_ce_up(info);
+
+ return;
+}
+
+static void check_data_length(void)
+{
+ uint8_t tmp;
+ /* Data length check, 4 bytes */
+ write_addr_port(SUPERIO_REG8, LPC_ADDR_PORT);
+ tmp = read_data_port(LPC_DATA_PORT);
+ if (tmp != SUPERIO_A2) {
+ write_data_port(SUPERIO_A2, LPC_DATA_PORT);
+ }
+
+ return;
+}
+
+static void enable_ilpc2ahb(void)
+{
+ /* Write 0xAA then write 0xA5 twice to enable super IO*/
+ write_addr_port(DISABLE_LPC, LPC_ADDR_PORT);
+ write_addr_port(ENABLE_LPC, LPC_ADDR_PORT);
+ write_addr_port(ENABLE_LPC, LPC_ADDR_PORT);
+
+ /* Enable iLPC2AHB */
+ write_addr_port(SUPERIO_07, LPC_ADDR_PORT);
+ write_data_port(LPC_TO_AHB, LPC_DATA_PORT);
+ write_addr_port(SUPERIO_30, LPC_ADDR_PORT);
+ write_data_port(ENABLE_LPC_TO_AHB, LPC_DATA_PORT);
+
+ /* Data length */
+ check_data_length();
+
+ return;
+}
+
+static void disable_ilpc2ahb(void)
+{
+ /* disable ilpc2ahb */
+ write_addr_port(SUPERIO_30, LPC_ADDR_PORT);
+ write_data_port(DISABLE_LPC_TO_AHB, LPC_DATA_PORT);
+ /* disable super IO */
+ write_addr_port(DISABLE_LPC, LPC_ADDR_PORT);
+
+ return;
+}
+
+/* Enable CPU */
+static void enable_cpu(void)
+{
+ /* unlock SCU register */
+ write_bmc_reg(SCU_ADDR, UNLOCK_SCU_KEY);
+ /* enable ARM */
+ write_bmc_reg(REBOOT_CPU_REGISTER, SET_BMC_CPU_BOOT);
+ /* lock SCU register */
+ write_bmc_reg(SCU_ADDR, LOCK_SCU_KEY);
+
+ return;
+}
+
+/* diasble CPU */
+static void disable_cpu(void)
+{
+ uint32_t scu_hw_strap_val;
+
+ /* unlock SCU register */
+ write_bmc_reg(SCU_ADDR, UNLOCK_SCU_KEY);
+ /* disable ARM */
+ scu_hw_strap_val = read_bmc_reg(HARDWARE_STRAP_REGISTER);
+ write_bmc_reg(HARDWARE_STRAP_REGISTER, scu_hw_strap_val |0x01);
+ /* lock SCU register */
+ write_bmc_reg(SCU_ADDR, LOCK_SCU_KEY);
+
+ return;
+}
+
+static void enable_upgrade(void)
+{
+
+ enable_ilpc2ahb();
+ /* diasble CPU */
+ disable_cpu();
+ /* init CE control register */
+ write_bmc_reg(CE0_CONTROL_REGISTER, 0);
+ write_bmc_reg(CE1_CONTROL_REGISTER, 0);
+ /* disable WDT2 */
+ write_bmc_reg(WATCHDOG2_CONTROL, DISABLE_WATCHDOG);
+
+ return;
+}
+
+static void disable_upgrade(void)
+{
+ enable_cpu();
+ dbg_print(debug_on, "DEBUG 0x%x\n", read_bmc_reg(HARDWARE_STRAP_REGISTER));
+ disable_ilpc2ahb();
+
+ return;
+}
+
+static void watchdog_status_debug(void)
+{
+ uint32_t watchdog_reg;
+
+ /* Watchdog Control Register */
+ watchdog_reg = read_bmc_reg(WATCHDOG2_CONTROL);
+ dbg_print(debug_on,"Watchdog Control Register: 0x%x\n", watchdog_reg);
+ dbg_print(debug_on,"Watchdog Enable Signal: 0x%x\n", watchdog_reg & BIT1);
+ dbg_print(debug_on,"Watchdog Reset SyS En: 0x%x\n", (watchdog_reg & BIT2) >> 1);
+ dbg_print(debug_on,"Watchdog Reset Mode: 0x%x\n", (watchdog_reg & (BIT6 | BIT7)) >> 5);
+ switch (watchdog_reg & (BIT6 | BIT7)) {
+ case SOC_SYS:
+ dbg_print(debug_on,"\tReset Mode En: SoC System\n");
+ break;
+ case FULL_CHIP:
+ dbg_print(debug_on,"\tReset Mode En: Full Chip\n");
+ break;
+ case ARM_CPU:
+ dbg_print(debug_on,"\tReset Mode En: ARM Cpu\n");
+ break;
+ default:
+ break;
+ }
+
+ /* Watchdog Timeout Status Register */
+ watchdog_reg = read_bmc_reg(WATCHDOG2_TSR);
+ dbg_print(debug_on,"Watchdog Timeout Occur: 0x%x\n", watchdog_reg & BIT1);
+ dbg_print(debug_on,"Watchdog Boot from: CD%d\n", watchdog_reg & BIT2);
+ dbg_print(debug_on,"Watchdog Interrupt Occur: 0x%x\n", watchdog_reg & BIT3);
+
+ return;
+}
+
+/* CE Type Setting Register */
+static void ce_type_setting_debug(void)
+{
+ uint32_t fmc_reg;
+
+ fmc_reg = read_bmc_reg(FMC_CE_TYPE_SETTING_REG);
+ if ((fmc_reg & CE0_SPI_TYPE) == SPI) {
+ dbg_print(debug_on,"CE0 Type Seeting: 0x%x, Type: SPI\n", fmc_reg & CE0_SPI_TYPE);
+ } else {
+ dbg_print(debug_on,"CE0 Type Seeting: 0x%x, Type: Unknown\n", fmc_reg & CE0_SPI_TYPE);
+ }
+ if (((fmc_reg & CE1_SPI_TYPE) >> BIT2) == SPI) {
+ dbg_print(debug_on,"CE1 Type Seeting: 0x%x, Type: SPI\n", (fmc_reg & CE1_SPI_TYPE) >> BIT2);
+ } else {
+ dbg_print(debug_on,"CE1 Type Seeting: 0x%x, Type: Unknown\n", (fmc_reg & CE1_SPI_TYPE) >> BIT2);
+ }
+
+ return;
+}
+/* CE Control Register */
+static void ce_control_debug(void)
+{
+ uint32_t fmc_reg;
+
+ fmc_reg = read_bmc_reg(CE_CONTROL_REGISTER);
+ dbg_print(debug_on,"CE0 Address Mode: 0x%x, Mode: %d Bytes\n",
+ fmc_reg & BIT1, (fmc_reg & BIT1) + 3);
+ dbg_print(debug_on,"CE1 Address Mode: 0x%x, Mode: %d Bytes\n",
+ (fmc_reg & BIT2) >> 1, ((fmc_reg & BIT2) >> 1) + 3);
+
+ return;
+}
+
+/* Interrupt Control & Status Register */
+static void irq_control_status_debug(void)
+{
+ uint32_t fmc_reg;
+
+ fmc_reg = read_bmc_reg(INR_STATUS_CONTROL_REGISTER);
+ dbg_print(debug_on,"SPI Write Address Protected Interrupt EN: 0x%x\n", fmc_reg & BIT2);
+ dbg_print(debug_on,"SPI Command Abort Interrupt EN: 0x%x\n", fmc_reg & BIT3);
+ dbg_print(debug_on,"SPI Write Address Protected Status: 0x%x, Status: %s\n",
+ RIGHT_SHIFT_8(fmc_reg) & BIT2, (RIGHT_SHIFT_8(fmc_reg) & BIT2) == BIT2 ? "Occur" : "Normal");
+ dbg_print(debug_on,"SPI Command Abort Status: 0x%x, Status: %s\n",
+ RIGHT_SHIFT_8(fmc_reg) & BIT3, (RIGHT_SHIFT_8(fmc_reg) & BIT3) == BIT3 ? "Occur" : "Normal");
+ /*Clear Abnormal Status*/
+ if ((RIGHT_SHIFT_8(fmc_reg) & BIT3) || (RIGHT_SHIFT_8(fmc_reg) & BIT2)) {
+ write_bmc_reg(INR_STATUS_CONTROL_REGISTER, CLEAR_INR_STATUS_CONTROL);
+ }
+
+ return;
+}
+
+/* Command Control Register */
+static void command_control_debug(void)
+{
+ uint32_t fmc_reg;
+
+ fmc_reg = read_bmc_reg(COMMAND_CONTROL_REGISTER);
+ dbg_print(debug_on,"Data Byte Line 0: %s\n", ((fmc_reg & BIT4) != 0) ? "Disable" : "Enable");
+ dbg_print(debug_on,"Data Byte Line 1: %s\n", ((fmc_reg & BIT3) != 0) ? "Disable" : "Enable");
+ dbg_print(debug_on,"Data Byte Line 2: %s\n", ((fmc_reg & BIT2) != 0) ? "Disable" : "Enable");
+ dbg_print(debug_on,"Data Byte Line 3: %s\n", ((fmc_reg & BIT1) != 0) ? "Disable" : "Enable");
+
+ dbg_print(debug_on,"Address Byte Line 0: %s\n", ((fmc_reg & BIT8) != 0) ? "Disable" : "Enable");
+ dbg_print(debug_on,"Address Byte Line 1: %s\n", ((fmc_reg & BIT7) != 0) ? "Disable" : "Enable");
+ dbg_print(debug_on,"Address Byte Line 2: %s\n", ((fmc_reg & BIT6) != 0) ? "Disable" : "Enable");
+ dbg_print(debug_on,"Address Byte Line 3: %s\n", ((fmc_reg & BIT5) != 0) ? "Disable" : "Enable");
+
+ return;
+}
+
+static void ce_control_reg_debug(void)
+{
+ uint32_t fmc_reg;
+
+ /* CE0 Control Register */
+ fmc_reg = read_bmc_reg(CE0_CONTROL_REGISTER);
+ switch (fmc_reg & (BIT1 | BIT2)){
+ case NORMAL_READ:
+ dbg_print(debug_on,"CE0 Command Mode: Normal Read\n");
+ break;
+ case READ_MODE:
+ dbg_print(debug_on,"CE0 Command Mode: Read Command\n");
+ break;
+ case WRITE_MODE:
+ dbg_print(debug_on,"CE0 Command Mode: Write Command\n");
+ break;
+ case USER_MODE:
+ dbg_print(debug_on,"CE0 Command Mode: User Mode\n");
+ break;
+ default:
+ break;
+ }
+ switch((RIGHT_SHIFT_24(fmc_reg) & (BIT5 | BIT6 | BIT7))){
+ case 0:
+ dbg_print(debug_on,"CE0 IO Mode: Single Mode\n");
+ break;
+ case 2:
+ case 3:
+ dbg_print(debug_on,"CE0 IO Mode: Dual Mode\n");
+ break;
+ default:
+ break;
+ }
+
+ dbg_print(debug_on,"CE0 Inactive Pulse Width: %d HCLK\n",
+ DEFAULT_WIDTH - (RIGHT_SHIFT_24(fmc_reg) & (BIT1 | BIT2 | BIT3 | BIT4)));
+ dbg_print(debug_on,"CE0 Data Input Mode: %s Mode\n", (fmc_reg & BIT4) == 0 ? "Single" : "Dual");
+ dbg_print(debug_on,"CE0 MSB | LSB: %s First\n", (fmc_reg & BIT6) == 0 ? "MSB" : "LSB");
+
+ /* CE1 Control Register */
+ fmc_reg = read_bmc_reg(CE1_CONTROL_REGISTER);
+ switch (fmc_reg & (BIT1 | BIT2)){
+ case NORMAL_READ:
+ dbg_print(debug_on,"CE1 Command Mode: Normal Read\n");
+ break;
+ case READ_MODE:
+ dbg_print(debug_on,"CE1 Command Mode: Read Command\n");
+ break;
+ case WRITE_MODE:
+ dbg_print(debug_on,"CE1 Command Mode: Write Command\n");
+ break;
+ case USER_MODE:
+ dbg_print(debug_on,"CE1 Command Mode: User Mode\n");
+ break;
+ default:
+ break;
+ }
+ switch((RIGHT_SHIFT_24(fmc_reg) & (BIT5 | BIT6 | BIT7))){
+ case 0:
+ dbg_print(debug_on,"CE1 IO Mode: Single Mode\n");
+ break;
+ case 2:
+ case 3:
+ dbg_print(debug_on,"CE1 IO Mode: Dual Mode\n");
+ break;
+ default:
+ break;
+ }
+
+ dbg_print(debug_on,"CE1 Inactive Pulse Width: %d HCLK\n",
+ DEFAULT_WIDTH - (RIGHT_SHIFT_24(fmc_reg) & (BIT1 | BIT2 | BIT3 | BIT4)));
+ dbg_print(debug_on,"CE1 Data Input Mode: %s Mode\n", (fmc_reg & BIT4) == 0 ? "Single" : "Dual");
+ dbg_print(debug_on,"CE1 MSB | LSB: %s First\n", (fmc_reg & BIT6) == 0 ? "MSB" : "LSB");
+
+ return;
+}
+
+static void fmc_debug(void)
+{
+ ce_type_setting_debug();
+ ce_control_debug();
+ irq_control_status_debug();
+ command_control_debug();
+ ce_control_reg_debug();
+
+ return;
+}
+
+/* Enable WatchDog to reset BMC*/
+static void enable_watchdog(int cs)
+{
+ uint32_t enable_watch_cmd;
+
+ enable_watch_cmd = (cs == CE0) ? ENABLE_WATCHDOG : ENABLE_WATCHDOG | BOOT_DEFAULT_MASK;
+ write_bmc_reg(WATCHDOG2_CLEAR_STATUS, CLEAR_WATCHDOG_STATUS);
+ write_bmc_reg(WATCHDOG2_RESET_FUN_MASK, WATCHDOG_GATEMASK);
+ write_bmc_reg(WATCHDOG2_RELOAD_VALUE, WATCHDOG_NEW_COUNT);
+ write_bmc_reg(WATCHDOG2_COUNTER_RST, WATCHDOG_RELOAD_COUNTER);
+ write_bmc_reg(WATCHDOG2_CONTROL, enable_watch_cmd);
+
+ return;
+}
+
+static void bmc_reboot(int cs)
+{
+ enable_watchdog(cs);
+ watchdog_status_debug();
+ disable_upgrade();
+ printf("Upgrade-Complete, BMC rebooting...\n");
+
+ return;
+}
+
+static int get_current_bmc(void)
+{
+ return (read_bmc_reg(WATCHDOG2_TSR) & 0x02) >> 1;
+}
+
+static void get_flash_base_and_ce_ctrl(int current_bmc, int cs, uint32_t *flash_base_addr, uint32_t *ce_ctrl_addr)
+{
+ uint32_t ce0_addr_range_reg_val, ce0_decode_addr;
+ uint32_t ce1_addr_range_reg_val, ce1_decode_addr;
+
+ ce0_addr_range_reg_val = read_bmc_reg(CE0_ADDRESS_RANGE_REGISTER);
+ ce0_decode_addr = SEGMENT_ADDR_START(ce0_addr_range_reg_val);
+ ce1_addr_range_reg_val = read_bmc_reg(CE1_ADDRESS_RANGE_REGISTER);
+ ce1_decode_addr = SEGMENT_ADDR_START(ce1_addr_range_reg_val);
+ dbg_print(debug_on,"CE0 addr decode range reg value:0x%08x, decode addr:0x%08x.\n",
+ ce0_addr_range_reg_val, ce0_decode_addr);
+ dbg_print(debug_on,"CE1 addr decode range reg value:0x%08x, decode addr:0x%08x.\n",
+ ce1_addr_range_reg_val, ce1_decode_addr);
+
+ if (((current_bmc == CURRENT_MASTER) && (cs ==CE0)) || ((current_bmc == CURRENT_SLAVE) && (cs ==CE1))) {
+ *ce_ctrl_addr = CE0_CONTROL_REGISTER;
+ *flash_base_addr = ce0_decode_addr;
+ } else {
+ *ce_ctrl_addr = CE1_CONTROL_REGISTER;
+ *flash_base_addr = ce1_decode_addr;
+ }
+
+ return;
+}
+
+static int get_flash_id(uint32_t flash_base_addr, uint32_t ce_ctrl_addr)
+{
+ uint32_t origin_flash_id, flash_id;
+
+ write_bmc_reg(ce_ctrl_addr, USER_MODE_PULL_CE_DOWN);
+ send_cmd(flash_base_addr, READID);
+ origin_flash_id = read_bmc_flash_data();
+ write_bmc_reg(ce_ctrl_addr, USER_MODE_PULL_CE_UP);
+ flash_id = origin_flash_id & 0xFFFFFF;
+ dbg_print(debug_on,"origin flash id:0x%x, flash id:0x%x\n", origin_flash_id, flash_id);
+
+ return flash_id;
+}
+
+static uint8_t get_flash_status(flash_info_t* info)
+{
+ uint8_t flash_status;
+
+ pull_ce_down(info);
+
+ send_cmd(info->flash_base_addr, READ_FLASH_STATUS);
+
+ flash_status = read_bmc_flash_data() & MASK;
+ pull_ce_up(info);
+
+ dbg_print(debug_on,"get_flash_status:0x%x\n", flash_status);
+ return flash_status;
+}
+
+static int check_flash_write_enable(flash_info_t* info)
+{
+ uint8_t flash_status;
+ int i, count;
+
+ count = FLASH_WEL_TIMEOUT / FLASH_WEL_SLEEP_TIME;
+ for (i = 0; i <= count; i++) {
+ flash_status = get_flash_status(info);
+ if ((flash_status & FLASH_WRITE_ENABLE_MASK) != FLASH_WRITE_ENABLE_MASK) {
+ usleep(FLASH_WEL_SLEEP_TIME);
+ } else {
+ dbg_print(debug_on,"Check flash WEL success, RDSR:0x%x\n", flash_status);
+ return 0;
+ }
+ }
+ printf("Check flash WEL timeout, RDSR:0x%x\n", flash_status);
+ return -1;
+}
+
+static int check_flash_write_process(flash_info_t* info, int timeout, int sleep_time)
+{
+ int i, count;
+ uint8_t flash_status;
+
+ count = timeout / sleep_time;
+ for (i = 0; i <= count; i++) {
+ flash_status = get_flash_status(info);
+ if ((flash_status & FLASH_WIP_MASK) != 0) {
+ usleep(sleep_time);
+ } else {
+ dbg_print(debug_on,"Check flash WIP success, RDSR:0x%x\n", flash_status);
+ return 0;
+ }
+ }
+ printf("Check flash WIP timeout, RDSR:0x%x.\n", flash_status);
+ return -1;
+}
+
+static int flash_write_enable(flash_info_t* info)
+{
+ int ret;
+
+ send_cmd_to_flash(info, WRITE_ENABLE_FLASH);
+ ret = check_flash_write_enable(info);
+ if (ret < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static void send_block_erase_cmd(flash_info_t* info, uint32_t block_addr)
+{
+ pull_ce_down(info);
+ send_cmd(info->flash_base_addr, info->erase_block_command);
+ write_bmc_flash_addr(block_addr); /* Erase Block addr */
+ pull_ce_up(info);
+
+ return;
+}
+
+static void send_chip_erase_cmd(flash_info_t* info)
+{
+ send_cmd_to_flash(info, CHIP_ERASE_FLASH);
+
+ return;
+}
+
+static int write_bmc_flash_page(flash_info_t* info, uint32_t page_addr, uint8_t *p, int len)
+{
+ int pos;
+
+ if (len % 4) {
+ printf("Page size %d invalid.\n", len);
+ return -1;
+ }
+
+ pos = 0;
+ pull_ce_down(info);
+ send_cmd(info->flash_base_addr, info->page_program);
+ write_bmc_flash_addr(page_addr); /* page address */
+ while (len) {
+ write_bmc_flash_data((*(uint32_t *)(p + pos)));
+ pos += 4;
+ len -= 4;
+ }
+ pull_ce_up(info);
+
+ return 0;
+}
+
+static int erase_chip_full(flash_info_t* info)
+{
+ time_t timep;
+ int ret;
+
+ if (info->full_erase == 0) {
+ printf("Flash not support full erase function.\n");
+ return -1;
+ }
+
+ ret = flash_write_enable(info);
+ if(ret < 0) {
+ printf("Chip erase, enable flash write error.\n");
+ return -1;
+ }
+
+ time(&timep);
+ printf("Full chip erasing, please wait...\n");
+ dbg_print(debug_on,"Erase Start-%s\n",asctime(gmtime(&timep)));
+ send_chip_erase_cmd(info);
+ ret = check_flash_write_process(info, CHIP_ERASE_TIMEOUT, CHIP_ERASE_SLEEP_TIME);
+ if (ret < 0) {
+ printf("Chip erase timeout.\n");
+ return -1;
+ }
+ time(&timep);
+ dbg_print(debug_on,"Erase Finish-%s\n",asctime(gmtime(&timep)));
+ printf("Erase Finish\n");
+ printf("=========================================\n");
+ return 0;
+}
+
+static int erase_chip_block(flash_info_t* info)
+{
+ uint32_t block_addr, end_addr;
+ time_t timep;
+ int ret;
+
+ printf("Block erasing...\n");
+ time (&timep);
+ dbg_print(debug_on,"Erase-Start-%s\n", asctime(gmtime(&timep)));
+ end_addr = info->flash_base_addr + info->flash_size;
+ block_addr = info->flash_base_addr;
+ while (1) {
+ /* Enable write */
+ ret = flash_write_enable(info);
+ if(ret < 0) {
+ printf("Block erase, enable flash write error, block addr:0x%x\n", block_addr);
+ return -1;
+ }
+
+ send_block_erase_cmd(info, block_addr);
+ /* Erase Block(64KB) MAX time 650ms*/
+ ret = check_flash_write_process(info, BLOCK_ERASE_TIMEOUT, BLOCK_ERASE_SLEEP_TIME);
+ if (ret < 0) {
+ printf("Block erase, check write status error, block addr:0x%x\n", block_addr);
+ return -1;
+ }
+ printf("\r0x%x", block_addr);
+ fflush(stdout);
+ if (block_addr >= end_addr) {
+ time(&timep);
+ printf("\r\nErase Finish\n");
+ printf("=========================================\n");
+ dbg_print(debug_on,"\nEnd-Earse-%s\n",asctime(gmtime(&timep)));
+ break;
+ }
+ block_addr += info->block_size;
+ }
+ return 0;
+}
+
+static int program_chip(uint32_t file_size, uint8_t *p, flash_info_t* info)
+{
+ time_t timep;
+ uint32_t page_addr, end_addr;
+ int ret, page_size;
+
+ page_addr = info->flash_base_addr;
+ page_size = info->page_size;
+ end_addr = file_size + info->flash_base_addr;
+ time (&timep);
+ printf("Programming...\n");
+ dbg_print(debug_on,"Program Start-%s\n",asctime(gmtime(&timep)));
+ /* Debug info */
+ fmc_debug();
+ while (1) {
+ /* Write enable */
+ ret = flash_write_enable(info);
+ if(ret < 0) {
+ printf("Page program, enable flash write error, page addr:0x%x\n", page_addr);
+ return -1;
+ }
+ ret = write_bmc_flash_page(info, page_addr, p, page_size);
+ if (ret < 0) {
+ printf("Page program, write bmc flash page error, page addr:0x%x\n", page_addr);
+ return -1;
+ }
+ /* page program MAX time 1.5ms */
+ ret = check_flash_write_process(info, PAGE_PROGRAM_TIMEOUT, PAGE_PROGRAM_SLEEP_TIME);
+ if (ret < 0) {
+ printf("Page program, check write status error, page addr:0x%x\n", page_addr);
+ return -1;
+ }
+ page_addr += page_size;
+ p += page_size;
+ if ((page_addr % 0x10000) == 0) {
+ printf("\r0x%x", page_addr);
+ fflush(stdout);
+ }
+
+ if (page_addr >= end_addr) {
+ printf("\nProgram Finish\n");
+ printf("=========================================\n");
+ time(&timep);
+ dbg_print(debug_on,"\nProgram-End-%s\n",asctime(gmtime(&timep)));
+ break;
+ }
+ } /* End of while (1) */
+ return 0;
+}
+
+static int check_chip(uint32_t file_size, uint8_t *p, flash_info_t* info)
+{
+ time_t timep;
+ uint32_t offset_addr, rd_val, end_addr;
+ int pos;
+
+ offset_addr = info->flash_base_addr;
+ end_addr = file_size + info->flash_base_addr;
+ pos=0;
+ /* Checking */
+ time(&timep);
+ printf("Checking...\n");
+ dbg_print(debug_on,"Checking-Start-%s\n",asctime(gmtime(&timep)));
+
+ pull_ce_down(info);
+ send_cmd(info->flash_base_addr, COMMON_FLASH_READ);
+ write_bmc_flash_addr(info->flash_base_addr);
+ while (1) {
+ if (offset_addr >= end_addr) {
+ break;
+ }
+ rd_val = read_bmc_flash_data();
+ if (rd_val != (*(uint32_t *)(p + pos))) {
+ printf("Check Error at 0x%08x\n", offset_addr);
+ printf("READ:0x%08x VALUE:0x%08x\n", rd_val, (*(uint32_t *)(p + pos)));
+ pull_ce_up(info);
+ return -1;
+ }
+ if ((offset_addr % 0x10000) == 0) {
+ printf("\r0x%x ", offset_addr);
+ fflush(stdout);
+ }
+ offset_addr += 4;
+ pos += 4;
+ }
+ pull_ce_up(info);
+ printf("\r\nFlash Checked\n");
+ printf("=========================================\n");
+ time(&timep);
+ dbg_print(debug_on,"Checking-End-%s\n",asctime(gmtime(&timep)));
+ return 0;
+}
+
+flash_info_t* get_flash_info(int current_bmc, int cs)
+{
+ int i, size;
+ uint32_t flash_base_addr, ce_ctrl_addr, flash_id;
+
+ get_flash_base_and_ce_ctrl(current_bmc, cs, &flash_base_addr, &ce_ctrl_addr);
+
+ size = (sizeof(flash_info) / sizeof((flash_info)[0]));
+
+ flash_id = get_flash_id(flash_base_addr, ce_ctrl_addr);
+ for (i = 0; i < size; i++) {
+ if (flash_info[i].flash_id == flash_id) {
+ flash_info[i].flash_base_addr = flash_base_addr;
+ flash_info[i].ce_control_reg = ce_ctrl_addr;
+ flash_info[i].cs = cs;
+ return &flash_info[i];
+ }
+ }
+ printf("Cannot get flash info, cs:%d, flash base addr:0x%x, ce control addr:0x%x, flash_id:0x%x.\n",
+ cs, flash_base_addr, ce_ctrl_addr, flash_id);
+ return NULL;
+}
+
+static void init_flash(flash_info_t* info)
+{
+ send_cmd_to_flash(info, RSTEN);
+ send_cmd_to_flash(info, RST);
+ send_cmd_to_flash(info, EXIT_OTP);
+ send_cmd_to_flash(info, ENABLE_BYTE4);
+
+ return;
+}
+
+static int upgrade_bmc_core(char *file_name, int erase_type, flash_info_t* info)
+{
+ int file_size, fp, ret;
+ uint8_t *p;
+
+ file_size = get_file_size(file_name);
+ if (file_size < 0) {
+ printf("file size %d Error\n", file_size);
+ return -1;
+ }
+
+ fp = open(file_name, O_RDWR);
+ if (fp < 0) {
+ printf("Cannot open %s.\n", file_name);
+ return -1;
+ }
+
+ p = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fp, 0);
+ if (p == MAP_FAILED) {
+ printf("Could not mmap %s, error(%s).\n", file_name, strerror(errno));
+ close(fp);
+ return -1;
+ }
+
+ printf("* CE%d FLASH TYPE: SPI FLASH\n", info->cs);
+ printf("* FLASH NAME: %s\n", info->flash_name);
+ printf("* File Size:%d, 0x%x\n", file_size, file_size);
+ printf("=========================================\n");
+
+ /* Select erase type */
+ switch (erase_type) {
+ case FULL_ERASE:
+ ret = erase_chip_full(info);
+ break;
+ case BLOCK_ERASE:
+ ret = erase_chip_block(info);
+ break;
+ default:
+ printf("Unsupport earse type:%d\n", erase_type);
+ goto exit;
+ break;
+ }
+
+ if (ret < 0) {
+ printf("Erase Chip Error\n");
+ goto exit;
+ }
+
+ /* Program the flash */
+ ret = program_chip(file_size, p, info);
+ if(ret < 0) {
+ printf("Program Chip Error\n");
+ goto exit;
+ }
+ /* Check */
+ ret = check_chip(file_size, p, info);
+ if(ret < 0) {
+ printf("Check Chip Error\n");
+ goto exit;
+ }
+
+ munmap(p, file_size);
+ close(fp);
+ return 0;
+exit:
+ munmap(p, file_size);
+ close(fp);
+ return -1;
+}
+
+static int upgrade_bmc_flash(char *filename, int current_bmc, int cs, int erase_type)
+{
+ int ret;
+ flash_info_t* info;
+
+ info = get_flash_info(current_bmc, cs);
+ if(info == NULL) {
+ return -1;
+ }
+
+ init_flash(info);
+
+ ret = upgrade_bmc_core(filename, erase_type, info);
+
+ return ret;
+}
+
+static int upgrade_both_flash(char *filename, int erase_type)
+{
+ int ret, current_bmc;
+
+ enable_upgrade();
+
+ current_bmc = get_current_bmc();
+ if (current_bmc == CURRENT_MASTER) {
+ printf("* Current Bmc Default Boot: CE0\n");
+ } else {
+ printf("* Current Bmc Default Boot: CE1\n");
+ }
+
+ ret = upgrade_bmc_flash(filename, current_bmc, CE0, erase_type);
+ if (ret < 0) {
+ printf("Upgrade master bmc flash failed, stop upgrade.\n");
+ goto err;
+ }
+ printf("Upgrade master bmc flash success.\n");
+
+ ret = upgrade_bmc_flash(filename, current_bmc, CE1, erase_type);
+ if (ret < 0) {
+ printf("Upgrade slave bmc flash failed.\n");
+ goto err;
+ }
+ printf("Upgrade slave bmc flash success.\n");
+
+ bmc_reboot(CE0);
+ return 0;
+err:
+ disable_upgrade();
+ return -1;
+}
+
+static int upgrade_single_flash(char *filename, int cs, int erase_type)
+{
+ int ret, current_bmc;
+
+ enable_upgrade();
+
+ current_bmc = get_current_bmc();
+ if (current_bmc == CURRENT_MASTER) {
+ printf("* Current Bmc Default Boot: CE0\n");
+ } else {
+ printf("* Current Bmc Default Boot: CE1\n");
+ }
+
+ ret = upgrade_bmc_flash(filename, current_bmc, cs, erase_type);
+ if (ret < 0) {
+ printf("Upgrade %s bmc flash failed.\n", cs == 0 ? "master":"slave");
+ goto err;
+ }
+ printf("Upgrade %s bmc flash success.\n", cs == 0 ? "master":"slave");
+
+ bmc_reboot(cs);
+ return 0;
+err:
+ disable_upgrade();
+ return -1;
+}
+
+static int upgrade_bmc(char *filename, int cs, int erase_type)
+{
+ int ret;
+
+ if (access(filename, F_OK) < 0) {
+ printf("Can't find file\n");
+ help();
+ return -1;
+ }
+
+ ret = set_ioport_rw_access();
+ if (ret < 0) {
+ printf("IO ERROR\n");
+ return -1;
+ }
+
+ switch(cs) {
+ /* Single */
+ case CE0:
+ case CE1:
+ ret = upgrade_single_flash(filename, cs, erase_type);
+ break;
+ /* Both */
+ case BOTHFLASH:
+ ret = upgrade_both_flash(filename, erase_type);
+ break;
+ default:
+ ret = -1;
+ printf("Unsupport cs:%d\n", cs);
+ break;
+ }
+
+ return ret;
+}
+
+static int read_single_bmc_flash(flash_info_t* info, uint32_t start_addr, int read_size, int is_print)
+{
+ uint32_t res, flash_start_addr, flash_end_addr;
+ char filename[MAX_FILENAME_LENGTH];
+ int fd, ret;
+
+ flash_start_addr = info->flash_base_addr + start_addr;
+ flash_end_addr = flash_start_addr + read_size;
+ ret = 0;
+ fd = 0;
+ if (!is_print) {
+ mem_clear(filename, MAX_FILENAME_LENGTH);
+ snprintf(filename, MAX_FILENAME_LENGTH, "/tmp/image-bmc%d", info->cs);
+ fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRWXG|S_IRWXU|S_IRWXO);
+ if (fd < 0) {
+ printf("open file %s fail(err:%d)!\r\n", filename, errno);
+ return -1;
+ }
+ }
+
+ printf("* CE%d FLASH TYPE: SPI FLASH\n", info->cs);
+ printf("* FLASH NAME: %s\n", info->flash_name);
+ printf("* Read flash addr:0x%x, size:0x%x\n", flash_start_addr, read_size);
+ printf("=========================================\n");
+ printf("Reading...\n");
+
+ pull_ce_down(info);
+ send_cmd(info->flash_base_addr, COMMON_FLASH_READ);
+ write_bmc_flash_addr(flash_start_addr);
+ while (1) {
+ if (flash_start_addr >= flash_end_addr) {
+ break;
+ }
+ res = read_bmc_flash_data();
+ if (is_print) {
+ printf("addr:0x%08x, val:0x%08x\n", flash_start_addr, res);
+ } else {
+ ret = write(fd, &res, sizeof(res));
+ if (ret < 0) {
+ printf("write failed (errno: %d).\n", errno);
+ ret = -1;
+ goto exit;
+ }
+ }
+ if (((flash_start_addr % 0x10000) == 0) && (!is_print)) {
+ printf("\r0x%x ", flash_start_addr);
+ fflush(stdout);
+ }
+ flash_start_addr += 4;
+ }
+ printf("\r\nRead Finish\n");
+ printf("=========================================\n");
+exit:
+ pull_ce_up(info);
+ if (fd > 0) {
+ close(fd);
+ }
+ return ret;
+}
+
+static int read_bmc_flash(int cs, uint32_t start_addr, int read_size, int is_print)
+{
+ int ret, current_bmc;
+ flash_info_t* info;
+
+ ret = set_ioport_rw_access();
+ if (ret < 0) {
+ printf("IO ERROR\n");
+ return -1;
+ }
+
+ enable_upgrade();
+
+ current_bmc = get_current_bmc();
+ if (current_bmc == CURRENT_MASTER) {
+ printf("* Current Bmc Default Boot: CE0\n");
+ } else {
+ printf("* Current Bmc Default Boot: CE1\n");
+ }
+
+ info = get_flash_info(current_bmc, cs);
+ if(info == NULL) {
+ goto err;
+ }
+
+ if (start_addr >= info->flash_size) {
+ printf("start_addr 0x%x out of range.\n", start_addr);
+ goto err;
+ }
+
+ if ((start_addr + read_size) > info->flash_size) {
+ printf("read size %d exceed flash size.\n", read_size);
+ read_size = info->flash_size - start_addr;
+ }
+
+ init_flash(info);
+
+ ret = read_single_bmc_flash(info, start_addr, read_size, is_print);
+ if (ret < 0) {
+ printf("Read %s bmc flash failed.\n", cs == 0 ? "master" : "slave");
+ goto err;
+ }
+ disable_upgrade();
+ return 0;
+err:
+ disable_upgrade();
+ return -1;
+}
+
+static int read_bmc_reg_main(int argc, char* argv[])
+{
+ uint32_t start_addr, read_val;
+ int read_size, ret;
+ char *stopstring;
+
+ if (argc != 4) {
+ printf("Input invalid.\n");
+ help();
+ return -1;
+ }
+
+ start_addr = strtoul(argv[2], &stopstring, 16);
+ read_size = strtol(argv[3], &stopstring, 10);
+
+ if (read_size <= 0) {
+ printf("read length %d invalid\n", read_size);
+ return -1;
+ }
+
+ if (((start_addr % 4) != 0) || ((read_size % 4) != 0)) {
+ printf("Params invalid, start_addr:0x%08x, read_size:%d\n", start_addr, read_size);
+ printf("Please input address/length times of 4\n");
+ return -1;
+ }
+
+ ret = set_ioport_rw_access();
+ if (ret < 0) {
+ printf("IO ERROR\n");
+ return -1;
+ }
+
+ enable_ilpc2ahb();
+
+ printf("read bcm reg, start_addr:0x%08x, read length:%d\n", start_addr, read_size);
+ printf("===Addr=== | ===Cont===\n");
+ while (read_size) {
+ read_val = read_bmc_reg(start_addr);
+ printf("0x%08x | 0x%08x\n", start_addr, read_val);
+ start_addr += 4;
+ read_size -= 4;
+ }
+
+ disable_ilpc2ahb();
+ return 0;
+}
+
+static int write_bmc_reg_main(int argc, char* argv[])
+{
+ uint32_t addr, wr_val;
+ int ret;
+ char *stopstring;
+
+ if (argc != 4) {
+ printf("Input invalid.\n");
+ help();
+ return -1;
+ }
+
+ addr = strtoul(argv[2], &stopstring, 16);
+ wr_val = strtoul(argv[3], &stopstring, 16);
+
+ if (((addr & MASK_BYTE) != REGISTER_HEAD) || ((addr % 4) != 0)) {
+ printf("Address[0x%08x] invalid, address should be register address and times of 4.\n", addr);
+ return -1;
+ }
+
+ ret = set_ioport_rw_access();
+ if (ret < 0) {
+ printf("IO ERROR\n");
+ return -1;
+ }
+
+ printf("write bcm reg, addr:0x%08x, val:0x%08x\n", addr, wr_val);
+
+ enable_ilpc2ahb();
+ write_bmc_reg(addr, wr_val);
+ disable_ilpc2ahb();
+
+ return 0;
+}
+
+static int get_fmc_info_main(void)
+{
+ int ret;
+
+ ret = set_ioport_rw_access();
+ if (ret < 0) {
+ printf("IO ERROR\n");
+ return -1;
+ }
+
+ enable_ilpc2ahb();
+
+ debug_on = 3;
+ fmc_debug();
+ debug_on = 0;
+
+ disable_ilpc2ahb();
+ return 0;
+}
+
+static int program_flash_main(int argc, char* argv[])
+{
+ int cs, erase_way, ret;
+ char *stopstring;
+ char tmp[128];
+
+ if (argc != 5) {
+ printf("Input invalid.\n");
+ help();
+ return -1;
+ }
+
+ cs = strtol(argv[3], &stopstring, 10);
+ if ((strlen(stopstring) != 0) || cs < 0 || cs > 2) {
+ snprintf(tmp, sizeof(tmp), "%s", argv[3]);
+ printf("Incorrect chip select %s\n", tmp);
+ help();
+ return -1;
+ }
+
+ if (strcmp(argv[4], "full") == 0) {
+ erase_way = FULL_ERASE;
+ } else if (strcmp(argv[4], "block") == 0) {
+ erase_way = BLOCK_ERASE;
+ } else {
+ snprintf(tmp, sizeof(tmp), "%s", argv[4]);
+ printf("Incorrect erase type %s\n", tmp);
+ help();
+ return -1;
+ }
+
+ printf("============BMC Upgrade Tool=============\n");
+ ret = upgrade_bmc(argv[2], cs, erase_way);
+ return ret;
+}
+
+static int read_bmc_flash_main(int argc, char* argv[])
+{
+ int cs, ret, read_size, is_print;
+ uint32_t start_addr;
+ char *stopstring;
+ char tmp[128];
+
+ if (argc != 6) {
+ printf("Input invalid.\n");
+ help();
+ return -1;
+ }
+
+ cs = strtol(argv[2], &stopstring, 10);
+ if ((strlen(stopstring) != 0) || cs < 0 || cs > 1) {
+ snprintf(tmp, sizeof(tmp), "%s", argv[2]);
+ printf("Incorrect chip select %s\n", tmp);
+ help();
+ return -1;
+ }
+
+ start_addr = strtoul(argv[3], &stopstring, 16);
+ read_size = strtol(argv[4], &stopstring, 10);
+
+ if (read_size <= 0) {
+ printf("read length %d invalid\n", read_size);
+ return -1;
+ }
+
+ if (((start_addr % 4) != 0) || ((read_size % 4) != 0)) {
+ printf("Params invalid, start_addr:0x%08x, read_size:%d\n", start_addr, read_size);
+ printf("Please input address/length times of 4\n");
+ return -1;
+ }
+
+ if (strcmp(argv[5], "print") == 0) {
+ is_print = 1;
+ } else {
+ is_print = 0;
+ }
+
+ printf("============READ BMC FLASH=============\n");
+ ret = read_bmc_flash(cs, start_addr, read_size, is_print);
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ debug_on = fw_upgrade_debug();
+
+ if (argc < 2) {
+ help();
+ return -1;
+ }
+
+ if (argc == 2) {
+ if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
+ help();
+ return 0;
+ }
+ }
+
+ if (strcmp(argv[1], "rd") == 0) {
+ ret = read_bmc_reg_main(argc, argv);
+ if (ret < 0) {
+ printf("Read Failed\n");
+ }
+ return ret;
+ }
+
+ if (strcmp(argv[1], "wr") == 0 && debug_on == 3) {
+ ret = write_bmc_reg_main(argc, argv);
+ if (ret < 0) {
+ printf("Write Failed\n");
+ }
+ return ret;
+ }
+
+ if (strcmp(argv[1], "info") == 0) {
+ ret = get_fmc_info_main();
+ if (ret < 0) {
+ printf("Get fmc info Failed\n");
+ }
+ return ret;
+ }
+
+ if (strcmp(argv[1], "upgrade") == 0) {
+ ret = program_flash_main(argc, argv);
+ if (ret < 0) {
+ printf("Upgrade BMC failed.\n");
+ }
+ return ret;
+ }
+
+ if (strcmp(argv[1], "read_bmc_flash") == 0) {
+ ret = read_bmc_flash_main(argc, argv);
+ if (ret < 0) {
+ printf("Read BMC flash failed.\n");
+ }
+ return ret;
+ }
+
+ printf("Input invalid.\n");
+ help();
+
+ return -1;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/fw_upgrade_debug.c b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/fw_upgrade_debug.c
new file mode 100644
index 000000000000..a7a78d011011
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/fw_upgrade_debug.c
@@ -0,0 +1,51 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "fw_upgrade_debug.h"
+
+int fw_upgrade_debug(void)
+{
+ int size;
+ FILE *fp;
+ char debug_info[DEBUG_INFO_LEN];
+
+ fp = fopen(DEBUG_FILE, "r");
+ if (fp == NULL) {
+ return DEBUG_IGNORE;
+ }
+
+ mem_clear(debug_info, DEBUG_INFO_LEN);
+ size = fread(debug_info, DEBUG_INFO_LEN - 1, 1, fp);
+ if (size < 0) {
+ fclose(fp);
+ return DEBUG_IGNORE;
+ }
+
+ if (strncmp(debug_info, DEBUG_ON_INFO, 1) == 0) {
+ fclose(fp);
+ return DEBUG_APP_ON;
+ }
+
+ if (strncmp(debug_info, DEBUG_ON_KERN, 1) == 0) {
+ fclose(fp);
+ return DEBUG_KERN_ON;
+ }
+
+ if (strncmp(debug_info, DEBUG_ON_ALL, 1) == 0) {
+ fclose(fp);
+ return DEBUG_ALL_ON;
+ }
+
+ if (strncmp(debug_info, DEBUG_OFF_INFO, 1) == 0) {
+ fclose(fp);
+ return DEBUG_OFF;
+ }
+
+ fclose(fp);
+ return DEBUG_IGNORE;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/include/fw_upgrade.h b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/include/fw_upgrade.h
new file mode 100644
index 000000000000..bd806a94b154
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/include/fw_upgrade.h
@@ -0,0 +1,230 @@
+#ifndef _FW_UPGRADE_H_
+#define _FW_UPGRADE_H_
+
+#include "fw_upgrade_debug.h"
+
+#define dbg_print(debug, fmt, arg...) \
+ if (debug == DEBUG_APP_ON || debug == DEBUG_ALL_ON) \
+ { do{printf(fmt,##arg);} while(0); }
+
+/* LPC Interface */
+#define LPC_ADDR_PORT (0x4E)
+#define LPC_DATA_PORT (0x4F)
+
+/* FMC REGISTER ADDR */
+#define FMC_BASE_ADDR (0x1E620000)
+#define FMC_CE_TYPE_SETTING_REG (FMC_BASE_ADDR + 0x00)
+#define CE_CONTROL_REGISTER (FMC_BASE_ADDR + 0x04)
+#define INR_STATUS_CONTROL_REGISTER (FMC_BASE_ADDR + 0x08)
+#define COMMAND_CONTROL_REGISTER (FMC_BASE_ADDR + 0x0C)
+#define CE0_CONTROL_REGISTER (FMC_BASE_ADDR + 0x10)
+#define CE1_CONTROL_REGISTER (FMC_BASE_ADDR + 0x14)
+#define CE0_ADDRESS_RANGE_REGISTER (FMC_BASE_ADDR + 0x30)
+#define CE1_ADDRESS_RANGE_REGISTER (FMC_BASE_ADDR + 0x34)
+
+/* SCU REGISTER ADDR */
+#define SCU_ADDR (0x1E6E2000)
+#define HARDWARE_STRAP_REGISTER (SCU_ADDR + 0x70)
+#define REBOOT_CPU_REGISTER (SCU_ADDR + 0x7C)
+
+/* SCU KEY */
+#define UNLOCK_SCU_KEY (0x1688A8A8)
+#define LOCK_SCU_KEY (0x11111111)
+
+/* WATCHDOG REGISTER ADDR */
+#define WATCHDOG_ADDR (0x1E785000)
+#define WATCHDOG1_RELOAD_VALUE (WATCHDOG_ADDR + 0x04)
+#define WATCHDOG1_COUNTER_RST (WATCHDOG_ADDR + 0x08)
+#define WATCHDOG1_CONTROL (WATCHDOG_ADDR + 0x0C)
+#define WATCHDOG1_TSR (WATCHDOG_ADDR + 0x10)
+#define WATCHDOG1_CLEAR_STATUS (WATCHDOG_ADDR + 0x14)
+#define WATCHDOG1_RESET_FUN_MASK (WATCHDOG_ADDR + 0x1C)
+
+#define WATCHDOG2_RELOAD_VALUE (WATCHDOG_ADDR + 0x24)
+#define WATCHDOG2_COUNTER_RST (WATCHDOG_ADDR + 0x28)
+#define WATCHDOG2_CONTROL (WATCHDOG_ADDR + 0x2C)
+#define WATCHDOG2_TSR (WATCHDOG_ADDR + 0x30)
+#define WATCHDOG2_CLEAR_STATUS (WATCHDOG_ADDR + 0x34)
+#define WATCHDOG2_RESET_FUN_MASK (WATCHDOG_ADDR + 0x3C)
+
+/* User Mode Command */
+#define WRITE_STATUS (0x01)
+#define COMMON_PAGE_PROGRAM (0x02)
+#define COMMON_FLASH_READ (0x03)
+#define WRITE_DISABLE_FLASH (0x04)
+#define READ_FLASH_STATUS (0x05)
+#define WRITE_ENABLE_FLASH (0x06)
+#define PAGE_PROGRAM_FLASH (0x12)
+#define SECTOR_ERASE (0x20)
+#define CLEAR_FLAG (0x50)
+#define SUBBLOCK_ERASE (0x52)
+#define CHIP_ERASE_FLASH (0x60)
+#define BLOCK_ERASE_64 (0xD8)
+#define READID (0x9F)
+#define ENABLE_BYTE4 (0xB7)
+#define EXIT_OTP (0xC1)
+#define RSTEN (0x66)
+#define RST (0x99)
+
+#define BIT1 (0x01)
+#define BIT2 (0x02)
+#define BIT3 (0x04)
+#define BIT4 (0x08)
+#define BIT5 (0x10)
+#define BIT6 (0x20)
+#define BIT7 (0x40)
+#define BIT8 (0x80)
+#define RIGHT_SHIFT_8(reg) (reg >> 8)
+#define RIGHT_SHIFT_16(reg) (reg >> 16)
+#define RIGHT_SHIFT_24(reg) (reg >> 24)
+#define MASK (0xFF)
+#define FLASH_TYPE_MASK (BIT1 | BIT2)
+#define BOOT_DEFAULT_MASK (BIT8)
+#define HEAD_MASK (0x00FFFF00)
+#define MASK_BYTE (0xFF000000)
+#define BYTE1 (1)
+#define BYTE2 (2)
+#define BYTE4 (4)
+#define BYTE1_VAL (0)
+#define BYTE2_VAL (1)
+#define BYTE4_VAL (2)
+#define BYTE_RESERVED (3)
+
+/* SuperIO */
+#define SUPERIO_07 (0x07)
+#define SUPERIO_30 (0x30)
+#define SUPERIO_A0 (0xA0)
+#define SUPERIO_A2 (0xA2)
+#define SUPERIO_REG0 (0xF0)
+#define SUPERIO_REG1 (0xF1)
+#define SUPERIO_REG2 (0xF2)
+#define SUPERIO_REG3 (0xF3)
+#define SUPERIO_REG4 (0xF4)
+#define SUPERIO_REG5 (0xF5)
+#define SUPERIO_REG6 (0xF6)
+#define SUPERIO_REG7 (0xF7)
+#define SUPERIO_REG8 (0xF8)
+#define SUPERIO_FE (0xFE)
+
+/* SPI Command */
+#define HIGH_CLOCK (0x00000000)
+#define NORMAL_READ (0x00000000)
+#define READ_MODE (0x00000001)
+#define WRITE_MODE (0x00000002)
+#define USER_MODE (0x00000003)
+#define PULL_DOWN (0x00000000)
+#define PULL_UP (0x00000004)
+
+#define CHIP_ERASE_TIME (60)
+#define CHIP_ERASE_TIMEOUT (300 * 1000 * 1000)
+#define CHIP_ERASE_SLEEP_TIME (5 * 1000 * 1000)
+#define BLOCK_ERASE_TIMEOUT (10 * 1000 * 1000)
+#define BLOCK_ERASE_SLEEP_TIME (100 * 1000)
+#define PAGE_PROGRAM_TIMEOUT (100 * 1000)
+#define PAGE_PROGRAM_SLEEP_TIME (1000)
+#define FLASH_WEL_TIMEOUT (100 * 1000)
+#define FLASH_WEL_SLEEP_TIME (1000)
+#define FLASH_WIP_MASK (0x00000001)
+#define FLASH_WRITE_ENABLE_MASK (0x00000002)
+
+#define DATA_LENGTH_MASK (0xA2)
+#define TOGGLE_WRITE (0xCF)
+#define DISABLE_LPC (0xAA)
+#define ENABLE_LPC (0xA5)
+#define LPC_TO_AHB (0x0D)
+#define ENABLE_LPC_TO_AHB (0x01)
+#define DISABLE_LPC_TO_AHB (0x00)
+#define ENABLE_BMC_CPU_BOOT (0xF10BD286)
+#define DISABLE_BMC_CPU_BOOT (0xF10BD287)
+#define SET_BMC_CPU_BOOT (0x01)
+#define CLEAR_WATCHDOG_STATUS (0x01)
+#define DISABLE_WATCHDOG (0x00000030)
+#define ENABLE_WATCHDOG (0x00000033)
+#define WATCHDOG_GATEMASK (0x033FFFF3)
+#define WATCHDOG_NEW_COUNT (0x00050000)
+#define WATCHDOG_RELOAD_COUNTER (0x4755)
+
+#define CE0_SPI_TYPE (0x00000002)
+#define CE1_SPI_TYPE (0x00000008)
+#define ERROR_COMMAND (0x00000400)
+#define ADDRESS_PROTECT (0x00000200)
+#define CLEAR_INR_STATUS_CONTROL (ERROR_COMMAND | ADDRESS_PROTECT)
+#define USER_MODE_PULL_CE_DOWN (HIGH_CLOCK | USER_MODE | PULL_DOWN)
+#define USER_MODE_PULL_CE_UP (HIGH_CLOCK | USER_MODE | PULL_UP)
+
+#define STEP_64 (64 * 1024)
+#define STEP_256 (256 * 1024)
+#define BYTE_256 (256)
+
+#define CE0 (0)
+#define CE1 (1)
+#define BOTHFLASH (2)
+#define SOC_SYS (0)
+#define FULL_CHIP (1)
+#define ARM_CPU (2)
+#define FULL_ERASE (0)
+#define BLOCK_ERASE (1)
+#define READ_ALL (2)
+#define CURRENT_SLAVE (1)
+#define CURRENT_MASTER (0)
+#define REGISTER_HEAD (0x1e000000)
+#define DEFAULT_WIDTH (16)
+#define MAX_FILENAME_LENGTH (64)
+#define SEGMENT_ADDR_START(_r) ((((_r) >> 16) & 0xFF) << 23)
+
+typedef struct flash_info {
+ uint32_t flash_size;
+ int cs;
+ int flash_type;
+ uint32_t flash_id;
+ int page_size;
+ char flash_name[64];
+ int erase_block_command;
+ int page_program;
+ int block_size;
+ int full_erase;
+ uint32_t ce_control_reg;
+ uint32_t flash_base_addr;
+} flash_info_t;
+
+typedef enum flash_id {
+ MX25L6433F = 0x1920c2,
+ S25FL512S = 0x200201,
+ MX25l512 = 0x1a20c2,
+ STM25P64 = 0x172020,
+ STM25P128 = 0x182020,
+ N25Q256 = 0x19ba20,
+ N25Q512 = 0x20ba20,
+ W25X16 = 0x1530ef,
+ W25X64 = 0x1730ef,
+ W25Q64BV = 0x1740ef,
+ W25Q128BV = 0x1840ef,
+ W25Q256FV = 0x1940ef,
+ MX25L1605D = 0x1520C2,
+ MX25L12805D = 0x1820C2,
+ MX66L1G45G = 0x1B20C2,
+ SST25VF016B = 0x4125bf,
+ SST25VF064C = 0x4b25bf,
+ SST25VF040B = 0x8d25bf,
+ AT25DF161 = 0x02461F,
+ AT25DF321 = 0x01471F,
+ GD25Q256 = 0X1940c8,
+} flash_id_t;
+
+typedef enum flash_type {
+ NOR = 0,
+ SPI = 2,
+} flash_type_t;
+
+typedef enum flash_size {
+ M1 = 0x00080000,
+ M3 = 0x00200000, /* 3M */
+ M6 = 0x00400000, /* 6M */
+ M12 = 0x00800000, /* 12M */
+ M16 = 0x01000000, /* 16M */
+ M32 = 0x02000000, /* 32M */
+ M64 = 0x04000000, /* 64M */
+ M128 = 0x08000000, /* 128M */
+} flash_size_t;
+
+#endif /*_FW_UPGRADE_H_*/
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/include/fw_upgrade_debug.h b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/include/fw_upgrade_debug.h
new file mode 100644
index 000000000000..05911da62a7e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/app/fw_upgrade/fw_upgrade/include/fw_upgrade_debug.h
@@ -0,0 +1,25 @@
+#ifndef __FW_UPGRADE_DEBUG_H__
+#define __FW_UPGRADE_DEBUG_H__
+
+#include
+
+#define DEBUG_INFO_LEN 20
+#define DEBUG_FILE "/tmp/.fw_upgrade_debug"
+#define DEBUG_ON_ALL "3"
+#define DEBUG_ON_KERN "2"
+#define DEBUG_ON_INFO "1"
+#define DEBUG_OFF_INFO "0"
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+enum debug_s {
+ DEBUG_OFF = 0,
+ DEBUG_APP_ON,
+ DEBUG_KERN_ON,
+ DEBUG_ALL_ON,
+ DEBUG_IGNORE,
+};
+
+extern int fw_upgrade_debug(void);
+
+#endif /* End of __FW_UPGRADE_DEBUG_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/__init__.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/hysteresis.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/hysteresis.py
new file mode 100644
index 000000000000..81fd596e7fee
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/hysteresis.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python3
+import os
+import syslog
+import copy
+
+from plat_hal.baseutil import baseutil
+
+HYST_DEBUG_FILE = "/etc/.hysteresis_debug_flag"
+
+HYSTERROR = 1
+HYSTDEBUG = 2
+
+debuglevel = 0
+
+
+def hyst_debug(s):
+ if HYSTDEBUG & debuglevel:
+ syslog.openlog("FANCONTROL-HYST", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_DEBUG, s)
+
+
+def hyst_error(s):
+ if HYSTERROR & debuglevel:
+ syslog.openlog("FANCONTROL-HYST", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_ERR, s)
+
+
+class hysteresis(object):
+ __config = None
+ __hyst_config = None
+
+ def __init__(self):
+ self.__config = baseutil.get_monitor_config()
+ self.__hyst_config = copy.deepcopy(self.__config.get("hyst", {}))
+ # init check
+ errcnt = 0
+ errmsg = ""
+ self.debug_init()
+ for temp_hyst_conf in self.__hyst_config.values():
+ if temp_hyst_conf["flag"] == 0:
+ continue
+ for i in range(temp_hyst_conf["temp_min"], temp_hyst_conf["temp_max"] + 1):
+ if i not in temp_hyst_conf["rising"]:
+ errcnt -= 1
+ msg = "%s hyst config error, temp value %d not in rising curve;" % (temp_hyst_conf["name"], i)
+ hyst_error(msg)
+ errmsg += msg
+ if i not in temp_hyst_conf["descending"]:
+ errcnt -= 1
+ msg = "%s hyst config error, temp value %d not in descending curve;" % (temp_hyst_conf["name"], i)
+ hyst_error(msg)
+ errmsg += msg
+ if errcnt < 0:
+ raise KeyError(errmsg)
+
+ def debug_init(self):
+ global debuglevel
+ if os.path.exists(HYST_DEBUG_FILE):
+ debuglevel = debuglevel | HYSTDEBUG | HYSTERROR
+ else:
+ debuglevel = debuglevel & ~(HYSTDEBUG | HYSTERROR)
+
+ def get_temp_hyst_conf(self, temp_name):
+ temp_hyst_conf = self.__hyst_config.get(temp_name)
+ return temp_hyst_conf
+
+ def get_temp_update(self, hyst_para, current_temp):
+ temp = hyst_para["value"]
+ if temp is None:
+ return None
+ temp.append(current_temp)
+ del temp[0]
+ return temp
+
+ def duty_to_pwm(self, duty):
+ pwm = int(round(float(duty) * 255 / 100))
+ return pwm
+
+ def pwm_to_duty(self, pwm):
+ duty = int(round(float(pwm) * 100 / 255))
+ return duty
+
+ def calc_hyst_val(self, temp_name, temp_list):
+
+ temp_hyst_conf = self.get_temp_hyst_conf(temp_name)
+ hyst_min = temp_hyst_conf["hyst_min"]
+ hyst_max = temp_hyst_conf["hyst_max"]
+ temp_min = temp_hyst_conf["temp_min"]
+ temp_max = temp_hyst_conf["temp_max"]
+ rising = temp_hyst_conf["rising"]
+ descending = temp_hyst_conf["descending"]
+ last_hyst_value = temp_hyst_conf["last_hyst_value"]
+ current_temp = temp_list[1]
+ last_temp = temp_list[0]
+
+ hyst_debug("calc_hyst_val, temp_name: %s, current_temp: %s, last_temp: %s, last_hyst_value: %s" %
+ (temp_name, current_temp, last_temp, last_hyst_value))
+
+ if current_temp < temp_min:
+ hyst_debug("%s current_temp %s less than temp_min %s, set min hyst value: %s" %
+ (temp_name, current_temp, temp_min, hyst_min))
+ return hyst_min
+
+ if current_temp > temp_max:
+ hyst_debug("%s current_temp %s more than temp_max %s, set max hyst value: %s" %
+ (temp_name, current_temp, temp_max, hyst_max))
+ return hyst_max
+
+ if last_temp is None: # first time
+ hyst_value = rising[current_temp]
+ hyst_debug("last_temp is None, it's first hysteresis, using rising hyst value: %s" % hyst_value)
+ return hyst_value
+
+ if current_temp == last_temp: # temp unchanging
+ hyst_debug("current_temp equal last_temp, keep last hyst value: %s" % last_hyst_value)
+ return last_hyst_value
+
+ if current_temp > last_temp:
+ calc_hyst_value = rising[current_temp]
+ if calc_hyst_value < last_hyst_value:
+ hyst_value = last_hyst_value
+ else:
+ hyst_value = calc_hyst_value
+ hyst_debug("temp rising, last_hyst_value: %s, calc_hyst_value: %s, set hyst value: %s" %
+ (last_hyst_value, calc_hyst_value, hyst_value))
+ return hyst_value
+
+ calc_hyst_value = descending[current_temp]
+ if calc_hyst_value > last_hyst_value:
+ hyst_value = last_hyst_value
+ else:
+ hyst_value = calc_hyst_value
+ hyst_debug("temp descending, last_hyst_value: %s, calc_hyst_value: %s, set hyst value: %s" %
+ (last_hyst_value, calc_hyst_value, hyst_value))
+ return hyst_value
+
+ def cacl(self, temp_name, current_temp):
+ self.debug_init()
+ try:
+ temp_hyst_conf = self.get_temp_hyst_conf(temp_name)
+ if temp_hyst_conf is None:
+ hyst_debug("get %s hysteresis config failed" % temp_name)
+ return None
+
+ flag = temp_hyst_conf["flag"]
+ if flag != 1:
+ hyst_debug("%s hysteresis flag == 0, skip" % temp_name)
+ return None
+
+ temp = self.get_temp_update(temp_hyst_conf, current_temp)
+ if temp is None:
+ hyst_debug("get %s update failed" % temp_name)
+ return None
+
+ value = self.calc_hyst_val(temp_name, temp)
+
+ temp_hyst_conf["last_hyst_value"] = value
+
+ speed_type = temp_hyst_conf["type"]
+ if speed_type == "duty":
+ pwm = self.duty_to_pwm(value)
+ else:
+ pwm = value
+
+ hyst_debug("temp_name: %s, current_temp: %s, set pwm 0x%x" % (temp_name, current_temp, pwm))
+ return pwm
+ except Exception as e:
+ hyst_error("temp_name: %s calc hysteresis pwm error, msg: %s" % (temp_name, str(e)))
+ return None
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/openloop.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/openloop.py
new file mode 100644
index 000000000000..3bb46b286998
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/openloop.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python3
+import os
+import syslog
+
+from plat_hal.baseutil import baseutil
+
+OPENLOOP_DEBUG_FILE = "/etc/.openloop_debug_flag"
+
+OPENLOOPERROR = 1
+OPENLOOPDEBUG = 2
+
+debuglevel = 0
+
+
+def openloop_debug(s):
+ if OPENLOOPDEBUG & debuglevel:
+ syslog.openlog("FANCONTROL-OPENLOOP", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_DEBUG, s)
+
+
+def openloop_error(s):
+ if OPENLOOPERROR & debuglevel:
+ syslog.openlog("FANCONTROL-OPENLOOP", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_ERR, s)
+
+
+class openloop(object):
+ __config = None
+ __openloop_config = None
+
+ def __init__(self):
+ self.__config = baseutil.get_monitor_config()
+ self.__openloop_config = self.__config["openloop"]
+
+ def debug_init(self):
+ global debuglevel
+ if os.path.exists(OPENLOOP_DEBUG_FILE):
+ debuglevel = debuglevel | OPENLOOPDEBUG | OPENLOOPERROR
+ else:
+ debuglevel = debuglevel & ~(OPENLOOPDEBUG | OPENLOOPERROR)
+
+ def get_para(self, t):
+ para = self.__openloop_config.get(t)
+ return para
+
+ def linear_cacl(self, temp):
+ self.debug_init()
+ openloop_para = self.get_para("linear")
+ if openloop_para is None:
+ openloop_debug("linear openloop: get para failed")
+ return None
+
+ K = openloop_para["K"]
+ tin_min = openloop_para["tin_min"]
+ pwm_min = openloop_para["pwm_min"]
+ pwm_max = openloop_para["pwm_max"]
+ flag = openloop_para["flag"]
+
+ openloop_debug("linear openloop: flag: %s, k: %s, tin_min: %s, pwm_min: 0x%x, pwm_max: 0x%x"
+ % (flag, K, tin_min, pwm_min, pwm_max))
+
+ if flag != 1:
+ openloop_debug("linear openloop: flag == 0")
+ return None
+
+ if temp <= tin_min:
+ openloop_debug("linear openloop: temp = %d less than tin_min[%d]" % (temp, tin_min))
+ return pwm_min
+
+ pwm = int(pwm_min + (temp - tin_min) * K)
+ openloop_debug("linear openloop: cacl_pwm = 0x%x" % pwm)
+
+ pwm = min(pwm, pwm_max)
+ pwm = max(pwm, pwm_min)
+ openloop_debug("linear openloop: temp = %d, pwm = 0x%x" % (temp, pwm))
+ return pwm
+
+ def curve_cacl(self, temp):
+ self.debug_init()
+ openloop_para = self.get_para("curve")
+ if openloop_para is None:
+ openloop_debug("curve openloop: get para failed")
+ return None
+
+ a = openloop_para["a"]
+ b = openloop_para["b"]
+ c = openloop_para["c"]
+ tin_min = openloop_para["tin_min"]
+ pwm_min = openloop_para["pwm_min"]
+ pwm_max = openloop_para["pwm_max"]
+ flag = openloop_para["flag"]
+
+ openloop_debug("curve openloop: flag: %s, a: %s, b: %s, c: %s, tin_min: %s, pwm_min: 0x%x, pwm_max: 0x%x"
+ % (flag, a, b, c, tin_min, pwm_min, pwm_max))
+
+ if flag != 1:
+ openloop_debug("curve openloop: flag == 0")
+ return None
+
+ if temp <= tin_min:
+ openloop_debug("curve openloop: temp = %d less than tin_min[%d]" % (temp, tin_min))
+ return pwm_min
+
+ pwm = int(a * temp * temp + b * temp + c)
+ openloop_debug("curve openloop: cacl_pwm = 0x%x" % pwm)
+
+ pwm = min(pwm, pwm_max)
+ pwm = max(pwm, pwm_min)
+ openloop_debug("curve openloop: temp = %d, pwm = 0x%x" % (temp, pwm))
+ return pwm
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/pid.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/pid.py
new file mode 100644
index 000000000000..25c2069fea66
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/pid.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+import os
+import syslog
+import copy
+
+from plat_hal.baseutil import baseutil
+
+PID_DEBUG_FILE = "/etc/.pid_debug_flag"
+
+PIDERROR = 1
+PIDDEBUG = 2
+
+debuglevel = 0
+
+
+def pid_debug(s):
+ if PIDDEBUG & debuglevel:
+ syslog.openlog("FANCONTROL-PID", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_DEBUG, s)
+
+
+def pid_error(s):
+ if PIDERROR & debuglevel:
+ syslog.openlog("FANCONTROL-PID", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_ERR, s)
+
+
+class pid(object):
+ __config = None
+ __pid_config = None
+
+ def __init__(self):
+ self.__config = baseutil.get_monitor_config()
+ self.__pid_config = copy.deepcopy(self.__config["pid"])
+
+ def debug_init(self):
+ global debuglevel
+ if os.path.exists(PID_DEBUG_FILE):
+ debuglevel = debuglevel | PIDDEBUG | PIDERROR
+ else:
+ debuglevel = debuglevel & ~(PIDDEBUG | PIDERROR)
+
+ def get_para(self, name):
+ para = self.__pid_config.get(name)
+ return para
+
+ def get_temp_update(self, pid_para, current_temp):
+ temp = pid_para["value"]
+ if temp is None:
+ return None
+ temp.append(current_temp)
+ del temp[0]
+ return temp
+
+ def cacl(self, last_pwm, name, current_temp):
+ delta_pwm = 0
+ self.debug_init()
+ pid_debug("last_pwm = %d" % last_pwm)
+
+ pid_para = self.get_para(name)
+ if pid_para is None:
+ pid_debug("get %s pid para failed" % name)
+ return None
+
+ temp = self.get_temp_update(pid_para, current_temp)
+ if temp is None:
+ pid_debug("get %s update failed" % name)
+ return None
+
+ speed_type = pid_para["type"]
+ Kp = pid_para["Kp"]
+ Ki = pid_para["Ki"]
+ Kd = pid_para["Kd"]
+ target = pid_para["target"]
+ pwm_min = pid_para["pwm_min"]
+ pwm_max = pid_para["pwm_max"]
+ flag = pid_para["flag"]
+
+ pid_debug("%s pid para: flag: %s, speed_type: %s, Kp: %s, Ki: %s, Kd: %s, target: %s, pwm_min: 0x%x, pwm_max: 0x%x"
+ % (name, flag, speed_type, Kp, Ki, Kd, target, pwm_min, pwm_max))
+
+ if flag != 1:
+ pid_debug("%s pid flag == 0" % name)
+ return None
+
+ if speed_type == "duty":
+ current_pwm = round(last_pwm * 100 / 255)
+ else:
+ current_pwm = last_pwm
+
+ if temp[2] is None:
+ tmp_pwm = current_pwm
+ elif ((temp[0] is None) or (temp[1] is None)):
+ delta_pwm = Ki * (temp[2] - target)
+ tmp_pwm = current_pwm + delta_pwm
+ else:
+ delta_pwm = Kp * (temp[2] - temp[1]) + Ki * (temp[2] - target) + Kd * (temp[2] - 2 * temp[1] + temp[0])
+ tmp_pwm = current_pwm + delta_pwm
+
+ pid_debug("delta_pwm = %d" % delta_pwm)
+ if speed_type == "duty":
+ pwm = round(tmp_pwm * 255 / 100)
+ else:
+ pwm = int(tmp_pwm)
+
+ pwm = min(pwm, pwm_max)
+ pwm = max(pwm, pwm_min)
+ pid_debug("last_pwm = 0x%x, pwm = 0x%x" % (last_pwm, pwm))
+ return pwm
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/__init__.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/cust_fru.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/cust_fru.py
new file mode 100644
index 000000000000..940c722ce467
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/cust_fru.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import sys
+import os
+
+
+class CustFruException(Exception):
+ def __init__(self, message='custfrueerror', code=-100):
+ err = 'errcode: {0} message:{1}'.format(code, message)
+ Exception.__init__(self, err)
+ self.code = code
+ self.message = message
+
+
+class CustFru():
+ MAGIC_HEAD_INFO = 0x7a
+
+ _CUST_MAGIC_OFFSET = 0
+ _CUST_MAGIC_LEN = 1
+ _CUST_VERSION_OFFSET = 1
+ _CUST_VERSION_LEN = 6
+ _CUST_CRC_OFFSET = 7
+ _CUST_CRC_LEN = 1
+ _CUST_PRODUCT_NAME_OFFSET = 10
+ _CUST_PRODUCT_NAME_LEN = 17
+ _CUST_MANUFACTURER_OFFSET = 27
+ _CUST_MANUFACTURER_LEN = 7
+ _CUST_SERIAL_NUMBER_OFFSET = 34
+ _CUST_SERIAL_NUMBER_LEN = 25
+ _CUST_INPUT_TYPE_OFFSET = 78
+ _CUST_INPUT_TYPE_LEN = 2
+ _CUST_INPUT_OFFSET = 86
+ _CUST_INPUT_LEN = 15
+ _CUST_OUTPUT_OFFSET = 108
+ _CUST_OUTPUT_LEN = 11
+ _CUST_POWER_OFFSET = 200
+ _CUST_POWER_LEN = 10
+ _CUST_MANUFACTURER_DATE_OFFSET = 210
+ _CUST_MANUFACTURER_DATE_LEN = 3
+
+ def __init__(self):
+ self.magic = ""
+ self.version = ""
+ self.crc = ""
+ self.product_name = ""
+ self.manufacturer = ""
+ self.serial_number = ""
+ self.input_type = ""
+ self.input = ""
+ self.output = ""
+ self.power = ""
+ self.manufacturer_date = ""
+
+ def checksum(self, v):
+ result = 0
+ for item in v:
+ result += ord(item)
+ return (result & 0xff)
+
+ def decode(self, e2):
+ # header
+ e2_index = 0
+ head = ord(e2[0])
+ if head != self.MAGIC_HEAD_INFO:
+ raise CustFruException("Customization fru eeprom head info error, head:0x%x" % head, -10)
+ self.magic = "0x%02x" % self.MAGIC_HEAD_INFO
+
+ # version
+ version = "%s" % (e2[self._CUST_VERSION_OFFSET:self._CUST_VERSION_OFFSET + self._CUST_VERSION_LEN])
+ self.version = version.replace("\xff", "").strip()
+
+ # crc
+ crc_calc = self.checksum(e2[0:self._CUST_CRC_OFFSET])
+ if crc_calc != ord(e2[self._CUST_CRC_OFFSET]):
+ raise CustFruException("Customization fru eeprom crc check error, calc: 0x%x, read: 0x%x" % (crc_calc, ord(e2[self._CUST_CRC_OFFSET])), -10)
+ self.crc = crc_calc
+
+ # Product Name
+ product_name = "%s" % (e2[self._CUST_PRODUCT_NAME_OFFSET:self._CUST_PRODUCT_NAME_OFFSET + self._CUST_PRODUCT_NAME_LEN])
+ self.product_name = product_name.replace("\xff", "").strip()
+
+ # manufacturer
+ manufacturer = "%s" % (e2[self._CUST_MANUFACTURER_OFFSET:self._CUST_MANUFACTURER_OFFSET + self._CUST_MANUFACTURER_LEN])
+ self.manufacturer = manufacturer.strip()
+
+ # serial_number
+ serial_number = "%s" % (e2[self._CUST_SERIAL_NUMBER_OFFSET:self._CUST_SERIAL_NUMBER_OFFSET + self._CUST_SERIAL_NUMBER_LEN])
+ self.serial_number = serial_number.strip()
+
+ # input_type
+ input_type = "%s" % (e2[self._CUST_INPUT_TYPE_OFFSET:self._CUST_INPUT_TYPE_OFFSET + self._CUST_INPUT_TYPE_LEN])
+ self.input_type = input_type.strip()
+
+ # input
+ input = "%s" % (e2[self._CUST_INPUT_OFFSET:self._CUST_INPUT_OFFSET + self._CUST_INPUT_LEN])
+ self.input = input.strip()
+
+ # output
+ output = "%s" % (e2[self._CUST_OUTPUT_OFFSET:self._CUST_OUTPUT_OFFSET + self._CUST_OUTPUT_LEN])
+ self.output = output.strip()
+
+ # power
+ power = "%s" % (e2[self._CUST_POWER_OFFSET:self._CUST_POWER_OFFSET + self._CUST_POWER_LEN])
+ self.power = power.replace("\xff", "").strip()
+
+ # manufacturer_date
+ manufacturer_year = ord(e2[self._CUST_MANUFACTURER_DATE_OFFSET]) + 2000
+ manufacturer_month = ord(e2[self._CUST_MANUFACTURER_DATE_OFFSET + 1])
+ manufacturer_day = ord(e2[self._CUST_MANUFACTURER_DATE_OFFSET + 2])
+ self.manufacturer_date = "%04d-%02d-%02d" % (manufacturer_year, manufacturer_month, manufacturer_day)
+
+ return
+
+
+ def __str__(self):
+ formatstr = "Version : %s \n" \
+ "Product Name : %s \n" \
+ "Manufacturer : %s \n" \
+ "Serial Number : %s \n" \
+ "AC/DC Power Module : %s \n" \
+ "INPUT : %s \n" \
+ "OUTPUT : %s \n" \
+ "POWER : %s \n" \
+ "Manufacturer Date : %s \n"
+ str_tmp = formatstr % (self.version,
+ self.product_name,
+ self.manufacturer,
+ self.serial_number,
+ self.input_type,
+ self.input,
+ self.output,
+ self.power,
+ self.manufacturer_date)
+ return str_tmp.replace("\x00","")
+
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fantlv.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fantlv.py
new file mode 100644
index 000000000000..4be78e7fdc03
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fantlv.py
@@ -0,0 +1,192 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+
+class FantlvException(Exception):
+ def __init__(self, message='fantlverror', code=-100):
+ err = 'errcode: {0} message:{1}'.format(code, message)
+ Exception.__init__(self, err)
+ self.code = code
+ self.message = message
+
+
+class fan_tlv():
+ HEAD_INFO = "\x01\x7e\x01\xf1"
+ VERSION = 0x01
+ FLAG = 0x7E
+ HW_VER = 0X01
+ TYPE = 0xf1
+ TLV_LEN = 00
+ _FAN_TLV_HDR_LEN = 6
+ _FAN_TLV_CRC_LEN = 2
+
+ _FAN_TLV_TYPE_NAME = 0x02
+ _FAN_TLV_TYPE_SN = 0x03
+ _FAN_TLV_TYPE_HW_INFO = 0x05
+ _FAN_TLV_TYPE_DEV_TYPE = 0x06
+
+ @property
+ def dstatus(self):
+ return self._dstatus
+
+ @property
+ def typename(self):
+ return self._typename
+
+ @property
+ def typesn(self):
+ return self._typesn
+
+ @property
+ def typehwinfo(self):
+ return self._typehwinfo
+
+ @property
+ def typedevtype(self):
+ return self._typedevtype
+
+ def __init__(self):
+ self._typename = ""
+ self._typesn = ""
+ self._typehwinfo = ""
+ self._typedevtype = ""
+ self._dstatus = 0
+
+ def strtoarr(self, val):
+ s = []
+ if not isinstance(val, str):
+ return s
+ for index in val:
+ s.append(index)
+ return s
+
+ def hex_to_str(self, s):
+ len_t = len(s)
+ if len_t % 2 != 0:
+ return 0
+ ret = ""
+ for t in range(0, len_t / 2):
+ ret += chr(int(s[2 * t:2 * t + 2], 16))
+ return ret
+
+ def generate_fan_value(self):
+ bin_buffer = [chr(0xff)] * 256
+ bin_buffer[0] = chr(self.VERSION)
+ bin_buffer[1] = chr(self.FLAG)
+ bin_buffer[2] = chr(self.HW_VER)
+ bin_buffer[3] = chr(self.TYPE)
+
+ temp_t = "%08x" % self.typedevtype
+ typedevtype_t = self.hex_to_str(temp_t)
+ total_len = len(self.typename) + len(self.typesn) + \
+ len(self.typehwinfo) + len(typedevtype_t) + 8
+
+ bin_buffer[4] = chr(total_len >> 8)
+ bin_buffer[5] = chr(total_len & 0x00FF)
+
+ index_start = 6
+ bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_NAME)
+ bin_buffer[index_start + 1] = chr(len(self.typename))
+ bin_buffer[index_start + 2: index_start + 2 +
+ len(self.typename)] = self.strtoarr(self.typename)
+ index_start = index_start + 2 + len(self.typename)
+
+ bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_SN)
+ bin_buffer[index_start + 1] = chr(len(self.typesn))
+ bin_buffer[index_start + 2:index_start + 2 +
+ len(self.typesn)] = self.strtoarr(self.typesn)
+ index_start = index_start + 2 + len(self.typesn)
+
+ bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_HW_INFO)
+ bin_buffer[index_start + 1] = chr(len(self.typehwinfo))
+ bin_buffer[index_start + 2:index_start + 2 +
+ len(self.typehwinfo)] = self.strtoarr(self.typehwinfo)
+ index_start = index_start + 2 + len(self.typehwinfo)
+
+ bin_buffer[index_start] = chr(self._FAN_TLV_TYPE_DEV_TYPE)
+ bin_buffer[index_start + 1] = chr(len(typedevtype_t))
+ bin_buffer[index_start + 2:index_start + 2 +
+ len(typedevtype_t)] = self.strtoarr(typedevtype_t)
+ index_start = index_start + 2 + len(typedevtype_t)
+
+ crcs = fan_tlv.fancrc(''.join(bin_buffer[0:index_start]))
+ bin_buffer[index_start] = chr(crcs >> 8)
+ bin_buffer[index_start + 1] = chr(crcs & 0x00ff)
+ return bin_buffer
+
+ def decode(self, e2):
+ if e2[0:4] != self.HEAD_INFO:
+ raise FantlvException("Fan tlv head info error,not fan tlv type", -10)
+ ret = []
+ self.VERSION = ord(e2[0])
+ self.FLAG = ord(e2[1])
+ self.HW_VER = ord(e2[2])
+ self.TYPE = ord(e2[3])
+ self.TLV_LEN = (ord(e2[4]) << 8) | ord(e2[5])
+
+ tlv_index = self._FAN_TLV_HDR_LEN
+ tlv_end = self._FAN_TLV_HDR_LEN + self.TLV_LEN
+
+ if len(e2) < self._FAN_TLV_HDR_LEN + self.TLV_LEN + 2:
+ raise FantlvException("Fan tlv eeprom len error!", -2)
+ sumcrc = fan_tlv.fancrc(e2[0:self._FAN_TLV_HDR_LEN + self.TLV_LEN])
+ readcrc = ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN]
+ ) << 8 | ord(e2[self._FAN_TLV_HDR_LEN + self.TLV_LEN + 1])
+ if sumcrc != readcrc:
+ raise FantlvException("Fan tlv eeprom checksum error!", -1)
+ self._dstatus = 0
+ while (tlv_index + 2) < len(e2) and tlv_index < tlv_end:
+ s = self.decoder(
+ e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])])
+ tlv_index += ord(e2[tlv_index + 1]) + 2
+ ret.append(s)
+
+ return ret
+
+ @staticmethod
+ def fancrc(t):
+ crc = 0
+ for item in t:
+ crc += ord(item)
+ return crc
+
+ def decoder(self, t):
+ try:
+ name = ""
+ value = ""
+ _len = 0
+ if ord(t[0]) == self._FAN_TLV_TYPE_NAME:
+ name = "Product Name"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._typename = value
+ elif ord(t[0]) == self._FAN_TLV_TYPE_SN:
+ name = "serial Number"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._typesn = value
+ elif ord(t[0]) == self._FAN_TLV_TYPE_HW_INFO:
+ name = "hardware info"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._typehwinfo = value
+ elif ord(t[0]) == self._FAN_TLV_TYPE_DEV_TYPE:
+ name = "dev type"
+ _len = ord(t[1])
+ value = "0x"
+ for c in t[2:2 + ord(t[1])]:
+ value += "%02X" % (ord(c),)
+ self._typedevtype = int(value, 16)
+ except Exception as e:
+ print(e)
+ return {"name": name, "code": ord(t[0]), "value": value, "lens": _len}
+
+ def __str__(self):
+ formatstr = "VERSION : 0x%02x \n" \
+ " FLAG : 0x%02x \n" \
+ " HW_VER : 0x%02x \n" \
+ " TYPE : 0x%02x \n" \
+ "typename : %s \n" \
+ "typesn : %s \n" \
+ "typehwinfo : %s \n"
+ return formatstr % (self.VERSION, self.FLAG, self.HW_VER, self.TYPE,
+ self.typename, self.typesn, self.typehwinfo)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fru.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fru.py
new file mode 100644
index 000000000000..f95164e03601
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fru.py
@@ -0,0 +1,961 @@
+#!/usr/bin/python3
+import collections
+from datetime import datetime, timedelta
+from bitarray import bitarray
+
+
+__DEBUG__ = "N"
+
+
+class FruException(Exception):
+ def __init__(self, message='fruerror', code=-100):
+ err = 'errcode: {0} message:{1}'.format(code, message)
+ Exception.__init__(self, err)
+ self.code = code
+ self.message = message
+
+
+def e_print(err):
+ print("ERROR: " + err)
+
+
+def d_print(debug_info):
+ if __DEBUG__ == "Y":
+ print(debug_info)
+
+
+class FruUtil():
+ @staticmethod
+ def decodeLength(value):
+ a = bitarray(8)
+ a.setall(True)
+ a[0:1] = 0
+ a[1:2] = 0
+ x = ord(a.tobytes())
+ return x & ord(value)
+
+ @staticmethod
+ def minToData():
+ starttime = datetime(1996, 1, 1, 0, 0, 0)
+ endtime = datetime.now()
+ seconds = (endtime - starttime).total_seconds()
+ mins = seconds // 60
+ m = int(round(mins))
+ return m
+
+ @staticmethod
+ def getTimeFormat():
+ return datetime.now().strftime('%Y-%m-%d')
+
+ @staticmethod
+ def getTypeLength(value):
+ if value is None or len(value) == 0:
+ return 0
+ a = bitarray(8)
+ a.setall(False)
+ a[0:1] = 1
+ a[1:2] = 1
+ x = ord(a.tobytes())
+ return x | len(value)
+
+ @staticmethod
+ def checksum(b):
+ result = 0
+ for item in b:
+ result += ord(item)
+ return (0x100 - (result & 0xff)) & 0xff
+
+
+class BaseArea(object):
+ SUGGESTED_SIZE_COMMON_HEADER = 8
+ SUGGESTED_SIZE_INTERNAL_USE_AREA = 72
+ SUGGESTED_SIZE_CHASSIS_INFO_AREA = 32
+ SUGGESTED_SIZE_BOARD_INFO_AREA = 80
+ SUGGESTED_SIZE_PRODUCT_INFO_AREA = 80
+
+ INITVALUE = b'\x00'
+ resultvalue = INITVALUE * 256
+ COMMON_HEAD_VERSION = b'\x01'
+ __childList = None
+
+ def __init__(self, name="", size=0, offset=0):
+ self.__childList = []
+ self._offset = offset
+ self.name = name
+ self._size = size
+ self._isPresent = False
+ self._data = b'\x00' * size
+
+ @property
+ def childList(self):
+ return self.__childList
+
+ @childList.setter
+ def childList(self, value):
+ self.__childList = value
+
+ @property
+ def offset(self):
+ return self._offset
+
+ @offset.setter
+ def offset(self, value):
+ self._offset = value
+
+ @property
+ def size(self):
+ return self._size
+
+ @size.setter
+ def size(self, value):
+ self._size = value
+
+ @property
+ def data(self):
+ return self._data
+
+ @data.setter
+ def data(self, value):
+ self._data = value
+
+ @property
+ def isPresent(self):
+ return self._isPresent
+
+ @isPresent.setter
+ def isPresent(self, value):
+ self._isPresent = value
+
+
+class InternalUseArea(BaseArea):
+ pass
+
+
+class ChassisInfoArea(BaseArea):
+ pass
+
+
+class BoardInfoArea(BaseArea):
+ _boardTime = None
+ _fields = None
+ _mfg_date = None
+ areaversion = None
+ _boardversion = None
+ _language = None
+
+ def __str__(self):
+ formatstr = "version : %x\n" \
+ "length : %d \n" \
+ "language : %x \n" \
+ "mfg_date : %s \n" \
+ "boardManufacturer : %s \n" \
+ "boardProductName : %s \n" \
+ "boardSerialNumber : %s \n" \
+ "boardPartNumber : %s \n" \
+ "fruFileId : %s \n"
+
+ tmpstr = formatstr % (ord(self.boardversion), self.size,
+ self.language, self.getMfgRealData(),
+ self.boardManufacturer, self.boardProductName,
+ self.boardSerialNumber, self.boardPartNumber,
+ self.fruFileId)
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ tmpstr += "boardextra%d : %s \n" % (i, valtmpval)
+ else:
+ break
+
+ return tmpstr
+
+ def todict(self):
+ dic = collections.OrderedDict()
+ dic["boardversion"] = ord(self.boardversion)
+ dic["boardlength"] = self.size
+ dic["boardlanguage"] = self.language
+ dic["boardmfg_date"] = self.getMfgRealData()
+ dic["boardManufacturer"] = self.boardManufacturer
+ dic["boardProductName"] = self.boardProductName
+ dic["boardSerialNumber"] = self.boardSerialNumber
+ dic["boardPartNumber"] = self.boardPartNumber
+ dic["boardfruFileId"] = self.fruFileId
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ dic[valtmp] = valtmpval
+ else:
+ break
+ return dic
+
+ def decodedata(self):
+ index = 0
+ self.areaversion = self.data[index]
+ index += 1
+ d_print("decode length :%d class size:%d" %
+ ((ord(self.data[index]) * 8), self.size))
+ index += 2
+
+ timetmp = self.data[index: index + 3]
+ self.mfg_date = ord(timetmp[0]) | (
+ ord(timetmp[1]) << 8) | (ord(timetmp[2]) << 16)
+ d_print("decode getMfgRealData :%s" % self.getMfgRealData())
+ index += 3
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardManufacturer = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardManufacturer:%s" % self.boardManufacturer)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardProductName = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardProductName:%s" % self.boardProductName)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardSerialNumber = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardSerialNumber:%s" % self.boardSerialNumber)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.boardPartNumber = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode boardPartNumber:%s" % self.boardPartNumber)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.fruFileId = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode fruFileId:%s" % self.fruFileId)
+
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if self.data[index] != chr(0xc1):
+ templen = FruUtil.decodeLength(self.data[index])
+ tmpval = self.data[index + 1: index + templen + 1]
+ setattr(self, valtmp, tmpval)
+ index += templen + 1
+ d_print("decode boardextra%d:%s" % (i, tmpval))
+ else:
+ break
+
+ def fruSetValue(self, field, value):
+ tmp_field = getattr(self, field, None)
+ if tmp_field is not None:
+ setattr(self, field, value)
+
+ def recalcute(self):
+ d_print("boardInfoArea version:%x" % ord(self.boardversion))
+ d_print("boardInfoArea length:%d" % self.size)
+ d_print("boardInfoArea language:%x" % self.language)
+ self.mfg_date = FruUtil.minToData()
+ d_print("boardInfoArea mfg_date:%x" % self.mfg_date)
+
+ self.data = chr(ord(self.boardversion)) + \
+ chr(self.size // 8) + chr(self.language)
+
+ self.data += chr(self.mfg_date & 0xFF)
+ self.data += chr((self.mfg_date >> 8) & 0xFF)
+ self.data += chr((self.mfg_date >> 16) & 0xFF)
+
+ d_print("boardInfoArea boardManufacturer:%s" % self.boardManufacturer)
+ typelength = FruUtil.getTypeLength(self.boardManufacturer)
+ self.data += chr(typelength)
+ self.data += self.boardManufacturer
+
+ d_print("boardInfoArea boardProductName:%s" % self.boardProductName)
+ self.data += chr(FruUtil.getTypeLength(self.boardProductName))
+ self.data += self.boardProductName
+
+ d_print("boardInfoArea boardSerialNumber:%s" % self.boardSerialNumber)
+ self.data += chr(FruUtil.getTypeLength(self.boardSerialNumber))
+ self.data += self.boardSerialNumber
+
+ d_print("boardInfoArea boardPartNumber:%s" % self.boardPartNumber)
+ self.data += chr(FruUtil.getTypeLength(self.boardPartNumber))
+ self.data += self.boardPartNumber
+
+ d_print("boardInfoArea fruFileId:%s" % self.fruFileId)
+ self.data += chr(FruUtil.getTypeLength(self.fruFileId))
+ self.data += self.fruFileId
+
+ for i in range(1, 11):
+ valtmp = "boardextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ d_print("boardInfoArea boardextra%d:%s" % (i, valtmpval))
+ self.data += chr(FruUtil.getTypeLength(valtmpval))
+ if valtmpval is not None:
+ self.data += valtmpval
+ else:
+ break
+
+ self.data += chr(0xc1)
+
+ if len(self.data) > (self.size - 1):
+ incr = (len(self.data) - self.size) // 8 + 1
+ self.size += incr * 8
+
+ self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:]
+ d_print("self data:%d" % len(self.data))
+ d_print("self size:%d" % self.size)
+ d_print("adjust size:%d" % (self.size - len(self.data) - 1))
+ self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0]))
+
+ # checksum
+ checksum = FruUtil.checksum(self.data)
+ d_print("board info checksum:%x" % checksum)
+ self.data += chr(checksum)
+
+ def getMfgRealData(self):
+ starttime = datetime(1996, 1, 1, 0, 0, 0)
+ mactime = starttime + timedelta(minutes=self.mfg_date)
+ return mactime
+
+ @property
+ def language(self):
+ self._language = 25
+ return self._language
+
+ @property
+ def mfg_date(self):
+ return self._mfg_date
+
+ @mfg_date.setter
+ def mfg_date(self, val):
+ self._mfg_date = val
+
+ @property
+ def boardversion(self):
+ self._boardversion = self.COMMON_HEAD_VERSION
+ return self._boardversion
+
+ @property
+ def fruFileId(self):
+ return self._FRUFileID
+
+ @fruFileId.setter
+ def fruFileId(self, val):
+ self._FRUFileID = val
+
+ @property
+ def boardPartNumber(self):
+ return self._boardPartNumber
+
+ @boardPartNumber.setter
+ def boardPartNumber(self, val):
+ self._boardPartNumber = val
+
+ @property
+ def boardSerialNumber(self):
+ return self._boardSerialNumber
+
+ @boardSerialNumber.setter
+ def boardSerialNumber(self, val):
+ self._boardSerialNumber = val
+
+ @property
+ def boardProductName(self):
+ return self._boradProductName
+
+ @boardProductName.setter
+ def boardProductName(self, val):
+ self._boradProductName = val
+
+ @property
+ def boardManufacturer(self):
+ return self._boardManufacturer
+
+ @boardManufacturer.setter
+ def boardManufacturer(self, val):
+ self._boardManufacturer = val
+
+ @property
+ def boardTime(self):
+ return self._boardTime
+
+ @boardTime.setter
+ def boardTime(self, val):
+ self._boardTime = val
+
+ @property
+ def fields(self):
+ return self._fields
+
+ @fields.setter
+ def fields(self, val):
+ self._fields = val
+
+
+class ProductInfoArea(BaseArea):
+ _productManufacturer = None
+ _productAssetTag = None
+ _FRUFileID = None
+ _language = None
+
+ def __str__(self):
+ formatstr = "version : %x\n" \
+ "length : %d \n" \
+ "language : %x \n" \
+ "productManufacturer : %s \n" \
+ "productName : %s \n" \
+ "productPartModelName: %s \n" \
+ "productVersion : %s \n" \
+ "productSerialNumber : %s \n" \
+ "productAssetTag : %s \n" \
+ "fruFileId : %s \n"
+
+ tmpstr = formatstr % (ord(self.areaversion), self.size,
+ self.language, self.productManufacturer,
+ self.productName, self.productPartModelName,
+ self.productVersion, self.productSerialNumber,
+ self.productAssetTag, self.fruFileId)
+
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ tmpstr += "productextra%d : %s \n" % (i, valtmpval)
+ else:
+ break
+
+ return tmpstr
+
+ def todict(self):
+ dic = collections.OrderedDict()
+ dic["productversion"] = ord(self.areaversion)
+ dic["productlength"] = self.size
+ dic["productlanguage"] = self.language
+ dic["productManufacturer"] = self.productManufacturer
+ dic["productName"] = self.productName
+ dic["productPartModelName"] = self.productPartModelName
+ dic["productVersion"] = int(self.productVersion, 16)
+ dic["productSerialNumber"] = self.productSerialNumber
+ dic["productAssetTag"] = self.productAssetTag
+ dic["productfruFileId"] = self.fruFileId
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ dic[valtmp] = valtmpval
+ else:
+ break
+ return dic
+
+ def decodedata(self):
+ index = 0
+ self.areaversion = self.data[index] # 0
+ index += 1
+ d_print("decode length %d" % (ord(self.data[index]) * 8))
+ d_print("class size %d" % self.size)
+ index += 2
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productManufacturer = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productManufacturer:%s" % self.productManufacturer)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productName = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productName:%s" % self.productName)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productPartModelName = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productPartModelName:%s" % self.productPartModelName)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productVersion = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productVersion:%s" % self.productVersion)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productSerialNumber = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productSerialNumber:%s" % self.productSerialNumber)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.productAssetTag = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode productAssetTag:%s" % self.productAssetTag)
+
+ templen = FruUtil.decodeLength(self.data[index])
+ self.fruFileId = self.data[index + 1: index + templen + 1]
+ index += templen + 1
+ d_print("decode fruFileId:%s" % self.fruFileId)
+
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if self.data[index] != chr(0xc1) and index < self.size - 1:
+ templen = FruUtil.decodeLength(self.data[index])
+ if templen == 0:
+ break
+ tmpval = self.data[index + 1: index + templen + 1]
+ d_print("decode boardextra%d:%s" % (i, tmpval))
+ setattr(self, valtmp, tmpval)
+ index += templen + 1
+ else:
+ break
+
+ @property
+ def productVersion(self):
+ return self._productVersion
+
+ @productVersion.setter
+ def productVersion(self, name):
+ self._productVersion = name
+
+ @property
+ def areaversion(self):
+ self._areaversion = self.COMMON_HEAD_VERSION
+ return self._areaversion
+
+ @areaversion.setter
+ def areaversion(self, name):
+ self._areaversion = name
+
+ @property
+ def language(self):
+ self._language = 25
+ return self._language
+
+ @property
+ def productManufacturer(self):
+ return self._productManufacturer
+
+ @productManufacturer.setter
+ def productManufacturer(self, name):
+ self._productManufacturer = name
+
+ @property
+ def productName(self):
+ return self._productName
+
+ @productName.setter
+ def productName(self, name):
+ self._productName = name
+
+ @property
+ def productPartModelName(self):
+ return self._productPartModelName
+
+ @productPartModelName.setter
+ def productPartModelName(self, name):
+ self._productPartModelName = name
+
+ @property
+ def productSerialNumber(self):
+ return self._productSerialNumber
+
+ @productSerialNumber.setter
+ def productSerialNumber(self, name):
+ self._productSerialNumber = name
+
+ @property
+ def productAssetTag(self):
+ return self._productAssetTag
+
+ @productAssetTag.setter
+ def productAssetTag(self, name):
+ self._productAssetTag = name
+
+ @property
+ def fruFileId(self):
+ return self._FRUFileID
+
+ @fruFileId.setter
+ def fruFileId(self, name):
+ self._FRUFileID = name
+
+ def fruSetValue(self, field, value):
+ tmp_field = getattr(self, field, None)
+ if tmp_field is not None:
+ setattr(self, field, value)
+
+ def recalcute(self):
+ d_print("product version:%x" % ord(self.areaversion))
+ d_print("product length:%d" % self.size)
+ d_print("product language:%x" % self.language)
+ self.data = chr(ord(self.areaversion)) + \
+ chr(self.size // 8) + chr(self.language)
+
+ typelength = FruUtil.getTypeLength(self.productManufacturer)
+ self.data += chr(typelength)
+ self.data += self.productManufacturer
+
+ self.data += chr(FruUtil.getTypeLength(self.productName))
+ self.data += self.productName
+
+ self.data += chr(FruUtil.getTypeLength(self.productPartModelName))
+ self.data += self.productPartModelName
+
+ self.data += chr(FruUtil.getTypeLength(self.productVersion))
+ self.data += self.productVersion
+
+ self.data += chr(FruUtil.getTypeLength(self.productSerialNumber))
+ self.data += self.productSerialNumber
+
+ self.data += chr(FruUtil.getTypeLength(self.productAssetTag))
+ if self.productAssetTag is not None:
+ self.data += self.productAssetTag
+
+ self.data += chr(FruUtil.getTypeLength(self.fruFileId))
+ self.data += self.fruFileId
+
+ for i in range(1, 11):
+ valtmp = "productextra%d" % i
+ if hasattr(self, valtmp):
+ valtmpval = getattr(self, valtmp)
+ d_print("boardInfoArea productextra%d:%s" % (i, valtmpval))
+ self.data += chr(FruUtil.getTypeLength(valtmpval))
+ if valtmpval is not None:
+ self.data += valtmpval
+ else:
+ break
+
+ self.data += chr(0xc1)
+ if len(self.data) > (self.size - 1):
+ incr = (len(self.data) - self.size) // 8 + 1
+ self.size += incr * 8
+ d_print("self.data:%d" % len(self.data))
+ d_print("self.size:%d" % self.size)
+
+ self.data = self.data[0:1] + chr(self.size // 8) + self.data[2:]
+ self.data = self.data.ljust((self.size - 1), chr(self.INITVALUE[0]))
+ checksum = FruUtil.checksum(self.data)
+ d_print("board info checksum:%x" % checksum)
+ self.data += chr(checksum)
+
+
+class MultiRecordArea(BaseArea):
+ pass
+
+
+class Field(object):
+
+ def __init__(self, fieldType="ASCII", fieldData=""):
+ self.fieldData = fieldData
+ self.fieldType = fieldType
+
+ @property
+ def fieldType(self):
+ return self.fieldType
+
+ @property
+ def fieldData(self):
+ return self.fieldData
+
+
+class ipmifru(BaseArea):
+ _BoardInfoArea = None
+ _ProductInfoArea = None
+ _InternalUseArea = None
+ _ChassisInfoArea = None
+ _multiRecordArea = None
+ _productinfoAreaOffset = BaseArea.INITVALUE
+ _boardInfoAreaOffset = BaseArea.INITVALUE
+ _internalUserAreaOffset = BaseArea.INITVALUE
+ _chassicInfoAreaOffset = BaseArea.INITVALUE
+ _multiRecordAreaOffset = BaseArea.INITVALUE
+ _bindata = None
+ _bodybin = None
+ _version = BaseArea.COMMON_HEAD_VERSION
+ _zeroCheckSum = None
+ _frusize = 256
+
+ def __str__(self):
+ tmpstr = ""
+ if self.boardInfoArea.isPresent:
+ tmpstr += "\nboardinfoarea: \n"
+ tmpstr += self.boardInfoArea.__str__()
+ if self.productInfoArea.isPresent:
+ tmpstr += "\nproductinfoarea: \n"
+ tmpstr += self.productInfoArea.__str__()
+ return tmpstr
+
+ def decodeBin(self, eeprom):
+ commonHead = eeprom[0:8]
+ d_print("decode version %x" % ord(commonHead[0]))
+ if ord(self.COMMON_HEAD_VERSION) != ord(commonHead[0]):
+ raise FruException("HEAD VERSION error,not Fru format!", -10)
+ if FruUtil.checksum(commonHead[0:7]) != ord(commonHead[7]):
+ strtemp = "check header checksum error [cal:%02x data:%02x]" % (
+ FruUtil.checksum(commonHead[0:7]), ord(commonHead[7]))
+ raise FruException(strtemp, -3)
+ if ord(commonHead[1]) != ord(self.INITVALUE):
+ d_print("Internal Use Area is present")
+ self.internalUseArea = InternalUseArea(
+ name="Internal Use Area", size=self.SUGGESTED_SIZE_INTERNAL_USE_AREA)
+ self.internalUseArea.isPresent = True
+ self.internalUserAreaOffset = ord(commonHead[1])
+ self.internalUseArea.data = eeprom[self.internalUserAreaOffset * 8: (
+ self.internalUserAreaOffset * 8 + self.internalUseArea.size)]
+ if ord(commonHead[2]) != ord(self.INITVALUE):
+ d_print("Chassis Info Area is present")
+ self.chassisInfoArea = ChassisInfoArea(
+ name="Chassis Info Area", size=self.SUGGESTED_SIZE_CHASSIS_INFO_AREA)
+ self.chassisInfoArea.isPresent = True
+ self.chassicInfoAreaOffset = ord(commonHead[2])
+ self.chassisInfoArea.data = eeprom[self.chassicInfoAreaOffset * 8: (
+ self.chassicInfoAreaOffset * 8 + self.chassisInfoArea.size)]
+ if ord(commonHead[3]) != ord(self.INITVALUE):
+ self.boardInfoArea = BoardInfoArea(
+ name="Board Info Area", size=self.SUGGESTED_SIZE_BOARD_INFO_AREA)
+ self.boardInfoArea.isPresent = True
+ self.boardInfoAreaOffset = ord(commonHead[3])
+ self.boardInfoArea.size = ord(
+ eeprom[self.boardInfoAreaOffset * 8 + 1]) * 8
+ d_print("Board Info Area is present size:%d" %
+ (self.boardInfoArea.size))
+ self.boardInfoArea.data = eeprom[self.boardInfoAreaOffset * 8: (
+ self.boardInfoAreaOffset * 8 + self.boardInfoArea.size)]
+ if FruUtil.checksum(self.boardInfoArea.data[:-1]) != ord(self.boardInfoArea.data[-1:]):
+ strtmp = "check boardInfoArea checksum error[cal:%02x data:%02x]" % \
+ (FruUtil.checksum(
+ self.boardInfoArea.data[:-1]), ord(self.boardInfoArea.data[-1:]))
+ raise FruException(strtmp, -3)
+ self.boardInfoArea.decodedata()
+ if ord(commonHead[4]) != ord(self.INITVALUE):
+ d_print("Product Info Area is present")
+ self.productInfoArea = ProductInfoArea(
+ name="Product Info Area ", size=self.SUGGESTED_SIZE_PRODUCT_INFO_AREA)
+ self.productInfoArea.isPresent = True
+ self.productinfoAreaOffset = ord(commonHead[4])
+ d_print("length offset value: %02x" %
+ ord(eeprom[self.productinfoAreaOffset * 8 + 1]))
+ self.productInfoArea.size = ord(
+ eeprom[self.productinfoAreaOffset * 8 + 1]) * 8
+ d_print("Product Info Area is present size:%d" %
+ (self.productInfoArea.size))
+
+ self.productInfoArea.data = eeprom[self.productinfoAreaOffset * 8: (
+ self.productinfoAreaOffset * 8 + self.productInfoArea.size)]
+ if FruUtil.checksum(self.productInfoArea.data[:-1]) != ord(self.productInfoArea.data[-1:]):
+ strtmp = "check productInfoArea checksum error [cal:%02x data:%02x]" % (
+ FruUtil.checksum(self.productInfoArea.data[:-1]), ord(self.productInfoArea.data[-1:]))
+ raise FruException(strtmp, -3)
+ self.productInfoArea.decodedata()
+ if ord(commonHead[5]) != ord(self.INITVALUE):
+ self.multiRecordArea = MultiRecordArea(
+ name="MultiRecord record Area ")
+ d_print("MultiRecord record present")
+ self.multiRecordArea.isPresent = True
+ self.multiRecordAreaOffset = ord(commonHead[5])
+ self.multiRecordArea.data = eeprom[self.multiRecordAreaOffset * 8: (
+ self.multiRecordAreaOffset * 8 + self.multiRecordArea.size)]
+
+ def initDefault(self):
+ self.version = self.COMMON_HEAD_VERSION
+ self.internalUserAreaOffset = self.INITVALUE
+ self.chassicInfoAreaOffset = self.INITVALUE
+ self.boardInfoAreaOffset = self.INITVALUE
+ self.productinfoAreaOffset = self.INITVALUE
+ self.multiRecordAreaOffset = self.INITVALUE
+ self.zeroCheckSum = self.INITVALUE
+ self.offset = self.SUGGESTED_SIZE_COMMON_HEADER
+ self.productInfoArea = None
+ self.internalUseArea = None
+ self.boardInfoArea = None
+ self.chassisInfoArea = None
+ self.multiRecordArea = None
+ # self.recalcute()
+
+ @property
+ def version(self):
+ return self._version
+
+ @version.setter
+ def version(self, name):
+ self._version = name
+
+ @property
+ def internalUserAreaOffset(self):
+ return self._internalUserAreaOffset
+
+ @internalUserAreaOffset.setter
+ def internalUserAreaOffset(self, obj):
+ self._internalUserAreaOffset = obj
+
+ @property
+ def chassicInfoAreaOffset(self):
+ return self._chassicInfoAreaOffset
+
+ @chassicInfoAreaOffset.setter
+ def chassicInfoAreaOffset(self, obj):
+ self._chassicInfoAreaOffset = obj
+
+ @property
+ def productinfoAreaOffset(self):
+ return self._productinfoAreaOffset
+
+ @productinfoAreaOffset.setter
+ def productinfoAreaOffset(self, obj):
+ self._productinfoAreaOffset = obj
+
+ @property
+ def boardInfoAreaOffset(self):
+ return self._boardInfoAreaOffset
+
+ @boardInfoAreaOffset.setter
+ def boardInfoAreaOffset(self, obj):
+ self._boardInfoAreaOffset = obj
+
+ @property
+ def multiRecordAreaOffset(self):
+ return self._multiRecordAreaOffset
+
+ @multiRecordAreaOffset.setter
+ def multiRecordAreaOffset(self, obj):
+ self._multiRecordAreaOffset = obj
+
+ @property
+ def zeroCheckSum(self):
+ return self._zeroCheckSum
+
+ @zeroCheckSum.setter
+ def zeroCheckSum(self, obj):
+ self._zeroCheckSum = obj
+
+ @property
+ def productInfoArea(self):
+ return self._ProductInfoArea
+
+ @productInfoArea.setter
+ def productInfoArea(self, obj):
+ self._ProductInfoArea = obj
+
+ @property
+ def internalUseArea(self):
+ return self._InternalUseArea
+
+ @internalUseArea.setter
+ def internalUseArea(self, obj):
+ self.internalUseArea = obj
+
+ @property
+ def boardInfoArea(self):
+ return self._BoardInfoArea
+
+ @boardInfoArea.setter
+ def boardInfoArea(self, obj):
+ self._BoardInfoArea = obj
+
+ @property
+ def chassisInfoArea(self):
+ return self._ChassisInfoArea
+
+ @chassisInfoArea.setter
+ def chassisInfoArea(self, obj):
+ self._ChassisInfoArea = obj
+
+ @property
+ def multiRecordArea(self):
+ return self._multiRecordArea
+
+ @multiRecordArea.setter
+ def multiRecordArea(self, obj):
+ self._multiRecordArea = obj
+
+ @property
+ def bindata(self):
+ return self._bindata
+
+ @bindata.setter
+ def bindata(self, obj):
+ self._bindata = obj
+
+ @property
+ def bodybin(self):
+ return self._bodybin
+
+ @bodybin.setter
+ def bodybin(self, obj):
+ self._bodybin = obj
+
+ def recalcuteCommonHead(self):
+ self.bindata = ""
+ self.offset = self.SUGGESTED_SIZE_COMMON_HEADER
+ d_print("common Header %d" % self.offset)
+ d_print("fru eeprom size %d" % self._frusize)
+ if self.internalUseArea is not None and self.internalUseArea.isPresent:
+ self.internalUserAreaOffset = self.offset // 8
+ self.offset += self.internalUseArea.size
+ d_print("internalUseArea is present offset:%d" % self.offset)
+
+ if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent:
+ self.chassicInfoAreaOffset = self.offset // 8
+ self.offset += self.chassisInfoArea.size
+ d_print("chassisInfoArea is present offset:%d" % self.offset)
+
+ if self.boardInfoArea is not None and self.boardInfoArea.isPresent:
+ self.boardInfoAreaOffset = self.offset // 8
+ self.offset += self.boardInfoArea.size
+ d_print("boardInfoArea is present offset:%d" % self.offset)
+ d_print("boardInfoArea is present size:%d" %
+ self.boardInfoArea.size)
+
+ if self.productInfoArea is not None and self.productInfoArea.isPresent:
+ self.productinfoAreaOffset = self.offset // 8
+ self.offset += self.productInfoArea.size
+ d_print("productInfoArea is present offset:%d" % self.offset)
+
+ if self.multiRecordArea is not None and self.multiRecordArea.isPresent:
+ self.multiRecordAreaOffset = self.offset // 8
+ d_print("multiRecordArea is present offset:%d" % self.offset)
+
+ if self.internalUserAreaOffset == self.INITVALUE:
+ self.internalUserAreaOffset = 0
+ if self.productinfoAreaOffset == self.INITVALUE:
+ self.productinfoAreaOffset = 0
+ if self.chassicInfoAreaOffset == self.INITVALUE:
+ self.chassicInfoAreaOffset = 0
+ if self.boardInfoAreaOffset == self.INITVALUE:
+ self.boardInfoAreaOffset = 0
+ if self.multiRecordAreaOffset == self.INITVALUE:
+ self.multiRecordAreaOffset = 0
+
+ self.zeroCheckSum = (0x100 - ord(self.version) - self.internalUserAreaOffset - self.chassicInfoAreaOffset - self.productinfoAreaOffset
+ - self.boardInfoAreaOffset - self.multiRecordAreaOffset) & 0xff
+ d_print("zerochecksum:%x" % self.zeroCheckSum)
+ self.data = ""
+ self.data += chr(self.version[0]) + chr(self.internalUserAreaOffset) + chr(self.chassicInfoAreaOffset) + chr(
+ self.boardInfoAreaOffset) + chr(self.productinfoAreaOffset) + chr(self.multiRecordAreaOffset) + chr(self.INITVALUE[0]) + chr(self.zeroCheckSum)
+
+ self.bindata = self.data + self.bodybin
+ totallen = len(self.bindata)
+ d_print("totallen %d" % totallen)
+ if totallen < self._frusize:
+ self.bindata = self.bindata.ljust(self._frusize, chr(self.INITVALUE[0]))
+ else:
+ raise FruException('bin data more than %d' % self._frusize, -2)
+
+ def recalcutebin(self):
+ self.bodybin = ""
+ if self.internalUseArea is not None and self.internalUseArea.isPresent:
+ d_print("internalUseArea present")
+ self.bodybin += self.internalUseArea.data
+ if self.chassisInfoArea is not None and self.chassisInfoArea.isPresent:
+ d_print("chassisInfoArea present")
+ self.bodybin += self.chassisInfoArea.data
+ if self.boardInfoArea is not None and self.boardInfoArea.isPresent:
+ d_print("boardInfoArea present")
+ self.boardInfoArea.recalcute()
+ self.bodybin += self.boardInfoArea.data
+ if self.productInfoArea is not None and self.productInfoArea.isPresent:
+ d_print("productInfoAreapresent")
+ self.productInfoArea.recalcute()
+ self.bodybin += self.productInfoArea.data
+ if self.multiRecordArea is not None and self.multiRecordArea.isPresent:
+ d_print("multiRecordArea present")
+ self.bodybin += self.productInfoArea.data
+
+ def recalcute(self, fru_eeprom_size=256):
+ self._frusize = fru_eeprom_size
+ self.recalcutebin()
+ self.recalcuteCommonHead()
+
+ def setValue(self, area, field, value):
+ tmp_area = getattr(self, area, None)
+ if tmp_area is not None:
+ tmp_area.fruSetValue(field, value)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/onietlv.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/onietlv.py
new file mode 100644
index 000000000000..a90f8f8453c8
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/onietlv.py
@@ -0,0 +1,441 @@
+#!/usr/bin/python3
+import binascii
+
+
+class OnietlvException(Exception):
+ def __init__(self, message='onietlverror', code=-100):
+ err = 'errcode: {0} message:{1}'.format(code, message)
+ Exception.__init__(self, err)
+ self.code = code
+ self.message = message
+
+
+class onie_tlv(object):
+ TLV_INFO_ID_STRING = "TlvInfo\x00"
+ TLV_INFO_INIA_ID = "\x00\x00\x13\x11"
+ TLV_INFO_VERSION = 0x01
+ TLV_INFO_LENGTH = 0x00
+ TLV_INFO_LENGTH_VALUE = 0xba
+
+ TLV_CODE_PRODUCT_NAME = 0x21
+ TLV_CODE_PART_NUMBER = 0x22
+ TLV_CODE_SERIAL_NUMBER = 0x23
+ TLV_CODE_MAC_BASE = 0x24
+ TLV_CODE_MANUF_DATE = 0x25
+ TLV_CODE_DEVICE_VERSION = 0x26
+ TLV_CODE_LABEL_REVISION = 0x27
+ TLV_CODE_PLATFORM_NAME = 0x28
+ TLV_CODE_ONIE_VERSION = 0x29
+ TLV_CODE_MAC_SIZE = 0x2A
+ TLV_CODE_MANUF_NAME = 0x2B
+ TLV_CODE_MANUF_COUNTRY = 0x2C
+ TLV_CODE_VENDOR_NAME = 0x2D
+ TLV_CODE_DIAG_VERSION = 0x2E
+ TLV_CODE_SERVICE_TAG = 0x2F
+ TLV_CODE_VENDOR_EXT = 0xFD
+ TLV_CODE_CRC_32 = 0xFE
+ _TLV_DISPLAY_VENDOR_EXT = 1
+ TLV_CODE_WB_CARID = 0x01
+ _TLV_INFO_HDR_LEN = 11
+ TLV_CODE_PRODUCT_ID = 0x40
+ TLV_CODE_HW_VERSION = 0x41
+ TLV_CODE_MAIN_FILENAME = 0x42
+ TLV_CODE_DTS_FINENAME = 0x43
+ TLV_CODE_SY_SERIAL0 = 0x44
+ TLV_CODE_SY_SERIAL1 = 0x45
+ TLV_CODE_SY_SERIAL2 = 0x46
+ TLV_CODE_SY_SERIAL3 = 0x47
+ TLV_CODE_PROJECT_ID = 0x48
+ TLV_CODE_SETMAC_VERSION = 0x49
+ TLV_CODE_EEPROM_TYPE = 0x4A
+
+ @property
+ def dstatus(self):
+ return self._dstatus
+
+ @property
+ def cardid(self):
+ return self._cardid
+
+ @property
+ def productname(self):
+ return self._productname
+
+ @property
+ def partnum(self):
+ return self._partnum
+
+ @property
+ def serialnum(self):
+ return self._serialnum
+
+ @property
+ def macbase(self):
+ return self._macbase
+
+ @property
+ def manufdate(self):
+ return self._manufdate
+
+ @property
+ def deviceversion(self):
+ return self._deviceversion
+
+ @property
+ def labelrevision(self):
+ return self._labelrevision
+
+ @property
+ def platformname(self):
+ return self._platformname
+
+ @property
+ def onieversion(self):
+ return self._onieversion
+
+ @property
+ def macsize(self):
+ return self._macsize
+
+ @property
+ def manufname(self):
+ return self._manufname
+
+ @property
+ def manufcountry(self):
+ return self._manufcountry
+
+ @property
+ def vendorname(self):
+ return self._vendorname
+
+ @property
+ def diagname(self):
+ return self._diagname
+
+ @property
+ def servicetag(self):
+ return self._servicetag
+
+ @property
+ def vendorext(self):
+ return self._vendorext
+
+ def __init__(self):
+ self._cardid = ""
+ self._productname = ""
+ self._partnum = ""
+ self._serialnum = ""
+ self._macbase = ""
+ self._manufdate = ""
+ self._deviceversion = ""
+ self._labelrevision = ""
+ self._platformname = ""
+ self._onieversion = ""
+ self._macsize = ""
+ self._manufname = ""
+ self._manufcountry = ""
+ self._vendorname = ""
+ self._diagname = ""
+ self._servicetag = ""
+ self._vendorext = ""
+ self._productid = ""
+ self._hwversion = ""
+ self._mainfilename = ""
+ self._dtsfilename = ""
+ self._syserial0 = ""
+ self._syserial1 = ""
+ self._syserial2 = ""
+ self._syserial3 = ""
+ self._projectid = ""
+ self._setmacversion = ""
+ self._eepromtype = ""
+ self._crc32 = ""
+ self._dstatus = 0
+
+ def oniecrc32(self, v):
+ data_array = bytearray()
+ for x in v:
+ data_array.append(ord(x))
+ return '0x%08x' % (binascii.crc32(bytes(data_array)) & 0xffffffff)
+
+ def getTLV_BODY(self, tlv_type, value):
+ x = []
+ temp_t = ""
+ if tlv_type == self.TLV_CODE_MAC_BASE:
+ arr = value.split(':')
+ for tt in arr:
+ temp_t += chr(int(tt, 16))
+ elif tlv_type == self.TLV_CODE_DEVICE_VERSION:
+ temp_t = chr(value)
+ elif tlv_type == self.TLV_CODE_MAC_SIZE:
+ temp_t = chr(value >> 8) + chr(value & 0x00ff)
+ else:
+ temp_t = value
+ x.append(chr(tlv_type))
+ x.append(chr(len(temp_t)))
+ for i in temp_t:
+ x.append(i)
+ return x
+
+ def generate_ext(self, cardid):
+ s = "%08x" % cardid
+ ret = ""
+ for t in range(0, 4):
+ ret += chr(int(s[2 * t:2 * t + 2], 16))
+ ret = chr(0x01) + chr(len(ret)) + ret
+ return ret
+
+ def generate_value(self, _t):
+ ret = []
+ for i in self.TLV_INFO_ID_STRING:
+ ret.append(i)
+ ret.append(chr(self.TLV_INFO_VERSION))
+ ret.append(chr(self.TLV_INFO_LENGTH))
+ ret.append(chr(self.TLV_INFO_LENGTH_VALUE))
+
+ total_len = 0
+ for key in _t:
+ x = self.getTLV_BODY(key, _t[key])
+ ret += x
+ total_len += len(x)
+ ret[10] = chr(total_len + 6)
+
+ ret.append(chr(0xFE))
+ ret.append(chr(0x04))
+ s = self.oniecrc32(''.join(ret))
+ for t in range(0, 4):
+ ret.append(chr(int(s[2 * t + 2:2 * t + 4], 16)))
+ totallen = len(ret)
+ if totallen < 256:
+ for left_t in range(0, 256 - totallen):
+ ret.append(chr(0x00))
+ return (ret, True)
+
+ def decode_tlv(self, e):
+ tlv_index = 0
+ tlv_end = len(e)
+ ret = []
+ while tlv_index < tlv_end and (tlv_index + 2 + ord(e[tlv_index + 1])) <= len(e):
+ rt = self.decoder(e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])])
+ ret.append(rt)
+ if ord(e[tlv_index]) == self.TLV_CODE_CRC_32:
+ break
+ tlv_index += ord(e[tlv_index + 1]) + 2
+ return ret
+
+ def decode(self, e):
+ if e[0:8] != self.TLV_INFO_ID_STRING:
+ raise OnietlvException("ONIE tlv head info error,not onie tlv type", -1)
+ total_len = (ord(e[9]) << 8) | ord(e[10])
+ tlv_index = self._TLV_INFO_HDR_LEN
+ tlv_end = self._TLV_INFO_HDR_LEN + total_len
+ if tlv_end > len(e):
+ raise OnietlvException("ONIE tlv length error", -2)
+ ret = []
+ ret = self.decode_tlv(e[tlv_index:tlv_end])
+ for item in ret:
+ if item['code'] == self.TLV_CODE_VENDOR_EXT:
+ if item["value"][0:4] == self.TLV_INFO_INIA_ID:
+ rt = self.decode_tlv(item["value"][4:])
+ else:
+ rt = self.decode_tlv(item["value"][0:])
+ ret.extend(rt)
+ return ret
+
+ def decoder(self, t):
+ if ord(t[0]) == self.TLV_CODE_PRODUCT_NAME:
+ name = "Product Name"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._productname = value
+ elif ord(t[0]) == self.TLV_CODE_PART_NUMBER:
+ name = "Part Number"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._partnum = value
+ elif ord(t[0]) == self.TLV_CODE_SERIAL_NUMBER:
+ name = "Serial Number"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._serialnum = value
+ elif ord(t[0]) == self.TLV_CODE_MAC_BASE:
+ name = "Base MAC Address"
+ _len = ord(t[1])
+ value = ":".join(['%02X' % ord(T) for T in t[2:8]]).upper()
+ self._macbase = value
+ elif ord(t[0]) == self.TLV_CODE_MANUF_DATE:
+ name = "Manufacture Date"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._manufdate = value
+ elif ord(t[0]) == self.TLV_CODE_DEVICE_VERSION:
+ name = "Device Version"
+ _len = ord(t[1])
+ value = ord(t[2])
+ self._deviceversion = value
+ elif ord(t[0]) == self.TLV_CODE_LABEL_REVISION:
+ name = "Label Revision"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._labelrevision = value
+ elif ord(t[0]) == self.TLV_CODE_PLATFORM_NAME:
+ name = "Platform Name"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._platformname = value
+ elif ord(t[0]) == self.TLV_CODE_ONIE_VERSION:
+ name = "ONIE Version"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._onieversion = value
+ elif ord(t[0]) == self.TLV_CODE_MAC_SIZE:
+ name = "MAC Addresses"
+ _len = ord(t[1])
+ value = str((ord(t[2]) << 8) | ord(t[3]))
+ self._macsize = value
+ elif ord(t[0]) == self.TLV_CODE_MANUF_NAME:
+ name = "Manufacturer"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._manufname = value
+ elif ord(t[0]) == self.TLV_CODE_MANUF_COUNTRY:
+ name = "Manufacture Country"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._manufcountry = value
+ elif ord(t[0]) == self.TLV_CODE_VENDOR_NAME:
+ name = "Vendor Name"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._vendorname = value
+ elif ord(t[0]) == self.TLV_CODE_DIAG_VERSION:
+ name = "Diag Version"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._diagname = value
+ elif ord(t[0]) == self.TLV_CODE_SERVICE_TAG:
+ name = "Service Tag"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._servicetag = value
+ elif ord(t[0]) == self.TLV_CODE_VENDOR_EXT:
+ name = "Vendor Extension"
+ _len = ord(t[1])
+ value = ""
+ if self._TLV_DISPLAY_VENDOR_EXT:
+ value = t[2:2 + ord(t[1])]
+ self._vendorext = value
+ elif ord(t[0]) == self.TLV_CODE_CRC_32 and len(t) == 6:
+ name = "CRC-32"
+ _len = ord(t[1])
+ value = "0x%08X" % (((ord(t[2]) << 24) | (
+ ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),)
+ self._crc32 = value
+ elif ord(t[0]) == self.TLV_CODE_WB_CARID:
+ name = "Card id"
+ _len = ord(t[1])
+ value = ""
+ for c in t[2:2 + ord(t[1])]:
+ value += "%02X" % (ord(c),)
+ self._cardid = value
+ elif ord(t[0]) == self.TLV_CODE_PRODUCT_ID:
+ name = "Product id"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._productid = value
+ elif ord(t[0]) == self.TLV_CODE_HW_VERSION:
+ name = "Hardware Version"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._hwversion = value
+ elif ord(t[0]) == self.TLV_CODE_MAIN_FILENAME:
+ name = "Main File Name"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._mainfilename = value
+ elif ord(t[0]) == self.TLV_CODE_DTS_FINENAME:
+ name = "DTS File Name"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._dtsfilename = value
+ elif ord(t[0]) == self.TLV_CODE_SY_SERIAL0:
+ name = "SY Serial 0"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._syserial0 = value
+ elif ord(t[0]) == self.TLV_CODE_SY_SERIAL1:
+ name = "SY Serial 1"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._syserial1 = value
+ elif ord(t[0]) == self.TLV_CODE_SY_SERIAL2:
+ name = "SY Serial 2"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._syserial2 = value
+ elif ord(t[0]) == self.TLV_CODE_SY_SERIAL3:
+ name = "SY Serial 3"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._syserial3 = value
+ elif ord(t[0]) == self.TLV_CODE_PROJECT_ID:
+ name = "Project id"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._projectid = value
+ elif ord(t[0]) == self.TLV_CODE_SETMAC_VERSION:
+ name = "Setmac Version"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._setmacversion = value
+ elif ord(t[0]) == self.TLV_CODE_EEPROM_TYPE:
+ name = "EEPROM Type"
+ _len = ord(t[1])
+ value = ""
+ for c in t[2:2 + ord(t[1])]:
+ value += "%02X" % (ord(c),)
+ self._eepromtype = value
+ else:
+ name = "Unknown"
+ _len = ord(t[1])
+ value = ""
+ for c in t[2:2 + ord(t[1])]:
+ value += "0x%02X " % (ord(c),)
+ return {"name": name, "code": ord(t[0]), "value": value, "lens": _len}
+
+ def __str__(self):
+ formatstr = "Card id : %s \n" \
+ "Product Name : %s \n" \
+ "Part Number : %s \n" \
+ "Serial Number : %s \n" \
+ "Base MAC Address : %s \n" \
+ "Manufacture Date : %s \n" \
+ "Device Version : %s \n" \
+ "Label Revision : %s \n" \
+ "Platform Name : %s \n" \
+ "ONIE Version : %s \n" \
+ "MAC Addresses : %s \n" \
+ "Manufacturer : %s \n" \
+ "Manufacture Country : %s \n" \
+ "Vendor Name : %s \n" \
+ "Diag Version : %s \n" \
+ "Service Tag : %s \n" \
+ "CRC-32 : %s \n"
+ return formatstr % (self._cardid,
+ self._productname,
+ self._partnum,
+ self._serialnum,
+ self._macbase,
+ self._manufdate,
+ self._deviceversion,
+ self._labelrevision,
+ self._platformname,
+ self._onieversion,
+ self._macsize,
+ self._manufname,
+ self._manufcountry,
+ self._vendorname,
+ self._diagname,
+ self._servicetag,
+ self._crc32)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/__init__.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/baseutil.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/baseutil.py
new file mode 100644
index 000000000000..5260107c91be
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/baseutil.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# baseutil.py
+# Python implementation of the Class baseutil
+#
+#######################################################
+import importlib.machinery
+import os
+import syslog
+import json
+from plat_hal.osutil import osutil
+
+SYSLOG_IDENTIFIER = "HAL"
+
+CONFIG_DB_PATH = "/etc/sonic/config_db.json"
+BOARD_ID_PATH = "/sys/module/platform_common/parameters/dfd_my_type"
+BOARD_AIRFLOW_PATH = "/etc/sonic/.airflow"
+
+
+def getonieplatform(path):
+ if not os.path.isfile(path):
+ return ""
+ machine_vars = {}
+ with open(path) as machine_file:
+ for line in machine_file:
+ tokens = line.split('=')
+ if len(tokens) < 2:
+ continue
+ machine_vars[tokens[0]] = tokens[1].strip()
+ return machine_vars.get("onie_platform")
+
+
+def getboardid():
+ if not os.path.exists(BOARD_ID_PATH):
+ return "NA"
+ with open(BOARD_ID_PATH) as fd:
+ id_str = fd.read().strip()
+ return "0x%x" % (int(id_str, 10))
+
+
+def getboardairflow():
+ if not os.path.exists(BOARD_AIRFLOW_PATH):
+ return "NA"
+ with open(BOARD_AIRFLOW_PATH) as fd:
+ airflow_str = fd.read().strip()
+ data = json.loads(airflow_str)
+ airflow = data.get("board", "NA")
+ return airflow
+
+
+def getplatform_config_db():
+ if not os.path.isfile(CONFIG_DB_PATH):
+ return ""
+ val = os.popen("sonic-cfggen -j %s -v DEVICE_METADATA.localhost.platform" % CONFIG_DB_PATH).read().strip()
+ if len(val) <= 0:
+ return ""
+ return val
+
+
+def getplatform_name():
+ if os.path.isfile('/host/machine.conf'):
+ return getonieplatform('/host/machine.conf')
+ if os.path.isfile('/etc/sonic/machine.conf'):
+ return getonieplatform('/etc/sonic/machine.conf')
+ return getplatform_config_db()
+
+
+platform = (getplatform_name()).replace("-", "_")
+boardid = getboardid()
+boardairflow = getboardairflow()
+
+
+CONFIG_FILE_PATH_LIST = [
+ "/usr/local/bin/",
+ "/usr/lib/python3/dist-packages/",
+ "/usr/local/lib/python3.7/dist-packages/hal-config/",
+ "/usr/local/lib/python3.9/dist-packages/hal-config/"
+]
+
+
+DEVICE_CONFIG_FILE_LIST = [
+ platform + "_" + boardid + "_" + boardairflow + "_device.py",
+ platform + "_" + boardid + "_device.py",
+ platform + "_" + boardairflow + "_device.py",
+ platform + "_device.py"
+]
+
+
+MONITOR_CONFIG_FILE_LIST = [
+ platform + "_" + boardid + "_" + boardairflow + "_monitor.py",
+ platform + "_" + boardid + "_monitor.py",
+ platform + "_" + boardairflow + "_monitor.py",
+ platform + "_monitor.py"
+]
+
+
+class baseutil:
+
+ CONFIG_NAME = 'devices'
+ MONITOR_CONFIG_NAME = 'monitor'
+ UBOOT_ENV_URL = '/etc/device/uboot_env'
+
+ @staticmethod
+ def get_config():
+ real_path = None
+ for configfile_path in CONFIG_FILE_PATH_LIST:
+ for config_file in DEVICE_CONFIG_FILE_LIST:
+ file = configfile_path + config_file
+ if os.path.exists(file):
+ real_path = file
+ break
+ if real_path is not None:
+ break
+
+ if real_path is None:
+ raise Exception("get hal device config error")
+ devices = importlib.machinery.SourceFileLoader(baseutil.CONFIG_NAME, real_path).load_module()
+ return devices.devices
+
+ @staticmethod
+ def get_monitor_config():
+ real_path = None
+ for configfile_path in CONFIG_FILE_PATH_LIST:
+ for config_file in MONITOR_CONFIG_FILE_LIST:
+ file = configfile_path + config_file
+ if os.path.exists(file):
+ real_path = file
+ break
+ if real_path is not None:
+ break
+
+ if real_path is None:
+ raise Exception("get hal monitor config error")
+ monitor = importlib.machinery.SourceFileLoader(baseutil.MONITOR_CONFIG_NAME, real_path).load_module()
+ return monitor.monitor
+
+ @staticmethod
+ def get_productname():
+ ret, val = osutil.command("cat %s |grep productname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL)
+ tmp = val.lower().replace('-', '_')
+ if ret != 0 or len(val) <= 0:
+ raise Exception("get productname error")
+ return tmp
+
+ @staticmethod
+ def get_platform():
+ ret, val = osutil.command("cat %s |grep conffitname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL)
+ if ret != 0 or len(val) <= 0:
+ raise Exception("get platform error")
+ return val
+
+ @staticmethod
+ def get_product_fullname():
+ ret, val = osutil.command("cat %s |grep productname | awk -F\"=\" '{print $2;}'" % baseutil.UBOOT_ENV_URL)
+ if ret != 0 or len(val) <= 0:
+ raise Exception("get productname error")
+ return val
+
+ @staticmethod
+ def logger_debug(msg):
+ syslog.openlog(SYSLOG_IDENTIFIER)
+ syslog.syslog(syslog.LOG_DEBUG, msg)
+ syslog.closelog()
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/chassisbase.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/chassisbase.py
new file mode 100644
index 000000000000..767d6da34ba9
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/chassisbase.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# chassisbase.py
+# Python implementation of the Class chassisbase
+#
+#######################################################
+from plat_hal.dcdc import dcdc
+from plat_hal.onie_e2 import onie_e2
+from plat_hal.psu import psu
+from plat_hal.led import led
+from plat_hal.temp import temp
+from plat_hal.fan import fan
+from plat_hal.cpld import cpld
+from plat_hal.component import component
+from plat_hal.cpu import cpu
+from plat_hal.baseutil import baseutil
+
+
+class chassisbase(object):
+ __onie_e2_list = []
+ __psu_list = []
+ __led_list = []
+ __temp_list = []
+ __fan_list = []
+ __card_list = []
+ __sensor_list = []
+ __dcdc_list = []
+ __cpld_list = []
+ __comp_list = []
+ __bios_list = []
+ __bmc_list = []
+ __cpu = None
+
+ def __init__(self, conftype=0, conf=None):
+ # type: (object, object, object) -> object
+ """
+ init chassisbase as order
+
+ type = 0 use default conf, maybe auto find by platform
+ type = 1 use given conf, conf is not None
+
+ BITMAP
+ bit 16
+ bit 0 PSU
+ bit 1 LED
+ bit 2 TEMP
+ bit 3 fan
+ bit 4 card
+ bit 5 sensor
+ """
+ __confTemp = None
+
+ if conftype == 0:
+ # user
+ __confTemp = baseutil.get_config()
+ elif conftype == 1:
+ __confTemp = conf
+
+ # onie_e2
+ onie_e2temp = []
+ onie_e2config = __confTemp.get('onie_e2', [])
+ for item in onie_e2config:
+ onie_e2_1 = onie_e2(item)
+ onie_e2temp.append(onie_e2_1)
+ self.onie_e2_list = onie_e2temp
+
+ # psu
+ psutemp = []
+ psuconfig = __confTemp.get('psus', [])
+ for item in psuconfig:
+ psu1 = psu(item)
+ psutemp.append(psu1)
+ self.psu_list = psutemp
+
+ # led
+ ledtemp = []
+ ledconfig = __confTemp.get('leds', [])
+ for item in ledconfig:
+ led1 = led(item)
+ ledtemp.append(led1)
+ self.led_list = ledtemp
+
+ # temp
+ temptemp = []
+ tempconfig = __confTemp.get('temps', [])
+ for item in tempconfig:
+ temp1 = temp(item)
+ temptemp.append(temp1)
+ self.temp_list = temptemp
+
+ # fan
+ fantemp = []
+ fanconfig = __confTemp.get('fans', [])
+ for item in fanconfig:
+ fan1 = fan(item)
+ fantemp.append(fan1)
+ self.fan_list = fantemp
+
+ # dcdc
+ dcdctemp = []
+ dcdcconfig = __confTemp.get('dcdc', [])
+ for item in dcdcconfig:
+ dcdc1 = dcdc(item)
+ dcdctemp.append(dcdc1)
+ self.dcdc_list = dcdctemp
+
+ # cpld
+ cpldtemp = []
+ cpldconfig = __confTemp.get('cplds', [])
+ for item in cpldconfig:
+ cpld1 = cpld(item)
+ cpldtemp.append(cpld1)
+ self.cpld_list = cpldtemp
+
+ # compoment: cpld/fpga/bios
+ comptemp = []
+ compconfig = __confTemp.get('comp_cpld', [])
+ for item in compconfig:
+ comp1 = component(item)
+ comptemp.append(comp1)
+ self.comp_list = comptemp
+
+ compconfig = __confTemp.get('comp_fpga', [])
+ for item in compconfig:
+ comp1 = component(item)
+ self.comp_list.append(comp1)
+
+ compconfig = __confTemp.get('comp_bios', [])
+ for item in compconfig:
+ comp1 = component(item)
+ self.comp_list.append(comp1)
+
+ # cpu
+ cpuconfig = __confTemp.get('cpu', [])
+ if len(cpuconfig):
+ self.cpu = cpu(cpuconfig[0])
+
+ # dcdc
+ @property
+ def dcdc_list(self):
+ return self.__dcdc_list
+
+ @dcdc_list.setter
+ def dcdc_list(self, val):
+ self.__dcdc_list = val
+
+ # sensor
+ @property
+ def sensor_list(self):
+ return self.__sensor_list
+
+ @sensor_list.setter
+ def sensor_list(self, val):
+ self.__sensor_list = val
+
+ def get_sensor_byname(self, name):
+ tmp = self.sensor_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # onie_e2
+ @property
+ def onie_e2_list(self):
+ return self.__onie_e2_list
+
+ @onie_e2_list.setter
+ def onie_e2_list(self, val):
+ self.__onie_e2_list = val
+
+ def get_onie_e2_byname(self, name):
+ tmp = self.onie_e2_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # psu
+ @property
+ def psu_list(self):
+ return self.__psu_list
+
+ @psu_list.setter
+ def psu_list(self, val):
+ self.__psu_list = val
+
+ def get_psu_byname(self, name):
+ tmp = self.psu_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # fan
+ @property
+ def fan_list(self):
+ return self.__fan_list
+
+ @fan_list.setter
+ def fan_list(self, val):
+ self.__fan_list = val
+
+ def get_fan_byname(self, name):
+ tmp = self.fan_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # led
+
+ @property
+ def led_list(self):
+ return self.__led_list
+
+ @led_list.setter
+ def led_list(self, val):
+ self.__led_list = val
+
+ def get_led_byname(self, name):
+ tmp = self.led_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # temp
+ @property
+ def temp_list(self):
+ return self.__temp_list
+
+ @temp_list.setter
+ def temp_list(self, val):
+ self.__temp_list = val
+
+ def get_temp_byname(self, name):
+ tmp = self.temp_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # cpld
+ @property
+ def cpld_list(self):
+ return self.__cpld_list
+
+ @cpld_list.setter
+ def cpld_list(self, val):
+ self.__cpld_list = val
+
+ def get_cpld_byname(self, name):
+ tmp = self.cpld_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ @property
+ def comp_list(self):
+ return self.__comp_list
+
+ @comp_list.setter
+ def comp_list(self, val):
+ self.__comp_list = val
+
+ def get_comp_byname(self, name):
+ tmp = self.comp_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # bios
+ @property
+ def bios_list(self):
+ return self.__bios_list
+
+ @bios_list.setter
+ def bios_list(self, val):
+ self.__bios_list = val
+
+ def get_bios_byname(self, name):
+ tmp = self.bios_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # bmc
+ @property
+ def bmc_list(self):
+ return self.__bmc_list
+
+ @bmc_list.setter
+ def bmc_list(self, val):
+ self.__bmc_list = val
+
+ def get_bmc_byname(self, name):
+ tmp = self.bmc_list
+ for item in tmp:
+ if name == item.name:
+ return item
+ return None
+
+ # cpu
+ @property
+ def cpu(self):
+ return self.__cpu
+
+ @cpu.setter
+ def cpu(self, val):
+ self.__cpu = val
+
+ def get_cpu_byname(self, name):
+ return self.cpu
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/component.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/component.py
new file mode 100644
index 000000000000..0f2ad2167485
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/component.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# component.py
+# Python implementation of the Class fan
+#
+#######################################################
+from plat_hal.devicebase import devicebase
+from plat_hal.osutil import osutil
+
+
+class component(devicebase):
+ __user_reg = None
+
+ def __init__(self, conf=None):
+ if conf is not None:
+ self.name = conf.get('name', None)
+ self.version_file = conf.get('VersionFile', None)
+ self.comp_id = conf.get("comp_id", None)
+ self.desc = conf.get("desc", None)
+ self.slot = conf.get("slot", None)
+
+ def get_version(self):
+ version = "NA"
+ try:
+ ret, version = self.get_value(self.version_file)
+ if ret is False:
+ return version
+ pattern = self.version_file.get('pattern', None)
+ version = osutil.std_match(version, pattern)
+ except Exception:
+ return version
+ return version
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/cpld.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/cpld.py
new file mode 100644
index 000000000000..09eed5f975ee
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/cpld.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# fan.py
+# Python implementation of the Class fan
+#
+#######################################################
+from plat_hal.devicebase import devicebase
+
+
+class cpld(devicebase):
+ __user_reg = None
+
+ def __init__(self, conf=None):
+ if conf is not None:
+ self.name = conf.get('name', None)
+ self.user_reg = conf.get('UserReg', None)
+ self.console_reg = conf.get('ConsoleReg', None)
+ self.console_reg_attrs = conf.get('ConsoleRegAttrs', None)
+ self.version_file = conf.get('VersionFile', None)
+ self.cpld_id = conf.get("cpld_id", None)
+ self.desc = conf.get("desc", None)
+ self.slot = conf.get("slot", None)
+ self.format = conf.get("format", "big_endian")
+ self.warm = conf.get("warm", None)
+ self.type = conf.get("type", None)
+
+ def get_user_reg(self):
+ if self.user_reg is None:
+ return False
+ ret, val = self.get_value(self.user_reg)
+ return val
+
+ def set_user_reg(self, value):
+ if self.user_reg is None:
+ return False
+ byte = value & 0xFF
+ ret, val = self.set_value(self.user_reg, byte)
+ return ret
+
+ def set_console_owner(self, owner):
+ ret = False
+
+ if self.console_reg is None:
+ return False
+ tmpattr = self.console_reg_attrs.get(owner, None)
+ if tmpattr is not None:
+ ret, val = self.set_value(self.console_reg, tmpattr)
+ return ret
+
+ def get_version(self):
+ ret, val = self.get_value(self.version_file)
+ if ret is False:
+ val = "N/A"
+ return val
+ if self.type == "str":
+ return val.strip('\n')
+ val = val.strip('\n').split(" ")
+ if len(val) < 4:
+ val = "N/A"
+ return val
+ if self.format == "little_endian":
+ cpld_version = "%s%s%s%s" % (val[3], val[2], val[1], val[0])
+ else:
+ cpld_version = "%s%s%s%s" % (val[0], val[1], val[2], val[3])
+ return cpld_version
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/cpu.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/cpu.py
new file mode 100644
index 000000000000..c6bec1abd1c2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/cpu.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+###############################################################################
+#
+# Hardware Abstraction Layer APIs -- CPU APIs.
+#
+###############################################################################
+from plat_hal.devicebase import devicebase
+
+
+class cpu(devicebase):
+
+ def __init__(self, conf=None):
+ if conf is not None:
+ self.name = conf.get('name', None)
+ self.cpu_reset_cnt_reg = conf.get('CpuResetCntReg', None)
+ self.reboot_cause_path = conf.get('reboot_cause_path', "/etc/sonic/.reboot/.previous-reboot-cause.txt")
+
+ def get_cpu_reset_num(self):
+ """
+ get cpu reset num.
+ @return cpu reset number, -1 for failure
+ """
+ ret = -1
+ if self.cpu_reset_cnt_reg is None:
+ self.logger_debug("ERR: no support get cpu reset num")
+ return ret
+ ret, reset_num = self.get_value(self.cpu_reset_cnt_reg)
+ if ret is False or reset_num is None:
+ self.logger_debug("ERR: i2c read cpu_reset_cnt_reg,result:%s" % reset_num)
+ else:
+ if isinstance(reset_num, str):
+ ret = int(reset_num, 16)
+ else:
+ ret = reset_num
+ return ret
+
+ def get_cpu_reboot_cause(self):
+ """
+ get_cpu_reboot_cause
+ @return cpu reset number, -1 for failure
+ """
+ try:
+ with open(self.reboot_cause_path) as fd:
+ reboot_cause = fd.read().strip()
+ return reboot_cause
+ except Exception:
+ return "Unknown reboot cause"
+
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/dcdc.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/dcdc.py
new file mode 100644
index 000000000000..ba604995043d
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/dcdc.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+from plat_hal.devicebase import devicebase
+from plat_hal.sensor import sensor
+
+
+class dcdc(devicebase):
+ def __init__(self, conf=None):
+ if conf is not None:
+ self.name = conf.get('name', None)
+ self.dcdc_id = conf.get("dcdc_id", None)
+ self.sensor = sensor(conf)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/devicebase.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/devicebase.py
new file mode 100644
index 000000000000..001b4ee239bf
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/devicebase.py
@@ -0,0 +1,351 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# devicebase.py
+# Python implementation of the Class devicebase
+#
+#######################################################
+import subprocess
+import shlex
+import ast
+from plat_hal.osutil import osutil
+from plat_hal.baseutil import baseutil
+
+class CodeVisitor(ast.NodeVisitor):
+
+ def __init__(self):
+ self.value = None
+
+ def get_value(self):
+ return self.value
+
+ def get_op_value(self, node):
+ if isinstance(node, ast.Call): # node is func call
+ value = self.visit_Call(node)
+ elif isinstance(node, ast.BinOp): # node is BinOp
+ value = self.visit_BinOp(node)
+ elif isinstance(node, ast.UnaryOp): # node is UnaryOp
+ value = self.visit_UnaryOp(node)
+ elif isinstance(node, ast.Num): # node is Num Constant
+ value = node.n
+ elif isinstance(node, ast.Str): # node is Str Constant
+ value = node.s
+ else:
+ raise NotImplementedError("Unsupport operand type: %s" % type(node))
+ return value
+
+ def visit_UnaryOp(self, node):
+ '''
+ node.op: operand type, only support ast.UAdd/ast.USub
+ node.operand: only support ast.Call/ast.Constant(ast.Num/ast.Str)/ast.BinOp/ast.UnaryOp
+ '''
+
+ operand_value = self.get_op_value(node.operand)
+ if isinstance(node.op, ast.UAdd):
+ self.value = operand_value
+ elif isinstance(node.op, ast.USub):
+ self.value = 0 - operand_value
+ else:
+ raise NotImplementedError("Unsupport arithmetic methods %s" % type(node.op))
+ return self.value
+
+ def visit_BinOp(self, node):
+ '''
+ node.left: left operand, only support ast.Call/ast.Constant(ast.Num)/ast.BinOp
+ node.op: operand type, only support ast.Add/ast.Sub/ast.Mult/ast.Div
+ node.right: right operan, only support ast.Call/ast.Constant(ast.Num/ast.Str)/ast.BinOp
+ '''
+ left_value = self.get_op_value(node.left)
+ right_value = self.get_op_value(node.right)
+
+ if isinstance(node.op, ast.Add):
+ self.value = left_value + right_value
+ elif isinstance(node.op, ast.Sub):
+ self.value = left_value - right_value
+ elif isinstance(node.op, ast.Mult):
+ self.value = left_value * right_value
+ elif isinstance(node.op, ast.Div):
+ self.value = left_value / right_value
+ else:
+ raise NotImplementedError("Unsupport arithmetic methods %s" % type(node.op))
+ return self.value
+
+ def visit_Call(self, node):
+ '''
+ node.func.id: func name, only support 'float', 'int', 'str'
+ node.args: func args list,only support ast.Constant(ast.Num/ast.Str)/ast.BinOp/ast.Call
+ str/float only support one parameter, eg: float(XXX), str(xxx)
+ int support one or two parameters, eg: int(xxx) or int(xxx, 16)
+ xxx can be ast.Call/ast.Constant(ast.Num/ast.Str)/ast.BinOp
+ '''
+ calc_tuple = ("float", "int", "str")
+
+ if node.func.id not in calc_tuple:
+ raise NotImplementedError("Unsupport function call type: %s" % node.func.id)
+
+ args_val_list = []
+ for item in node.args:
+ ret = self.get_op_value(item)
+ args_val_list.append(ret)
+
+ if node.func.id == "str":
+ if len(args_val_list) != 1:
+ raise TypeError("str() takes 1 positional argument but %s were given" % len(args_val_list))
+ value = str(args_val_list[0])
+ self.value = value
+ return value
+
+ if node.func.id == "float":
+ if len(args_val_list) != 1:
+ raise TypeError("float() takes 1 positional argument but %s were given" % len(args_val_list))
+ value = float(args_val_list[0])
+ self.value = value
+ return value
+ # int
+ if len(args_val_list) == 1:
+ value = int(args_val_list[0])
+ self.value = value
+ return value
+ if len(args_val_list) == 2:
+ value = int(args_val_list[0], args_val_list[1])
+ self.value = value
+ return value
+ raise TypeError("int() takes 1 or 2 arguments (%s given)" % len(args_val_list))
+
+
+class devicebase(object):
+ _name = None
+ __error_ret = -99999
+
+ @property
+ def name(self):
+ return self._name
+
+ @name.setter
+ def name(self, val):
+ self._name = val
+
+ def dumpValueByI2c(self, bus, loc):
+ value = ""
+ for i in range(256):
+ ret, val = self.get_i2c(bus, loc, i)
+ value += chr(val)
+ return value
+
+ def byteTostr(self, val):
+ strtmp = ''
+ for value in val:
+ strtmp += chr(value)
+ return strtmp
+
+ def get_eeprom_info(self, conf):
+ eeprom = ""
+ if conf.get('way') == 'sysfs':
+ ret, eeprom = self.get_value(conf)
+ if ret is False:
+ return None
+ elif conf.get('way') == 'devfile':
+ ret, eeprom_list = self.get_value(conf)
+ if ret is False:
+ return None
+ for item in eeprom_list:
+ eeprom += chr(item)
+ else:
+ eeprom = self.dumpValueByI2c(conf.get('bus'), conf.get('addr'))
+ return eeprom
+
+ def exec_os_cmd(self, cmd):
+ status, output = subprocess.getstatusoutput(cmd)
+ return status, output
+
+ def get_value(self, config):
+ '''
+ get value by config way
+ way i2c/sysfs/lpc
+ '''
+ way = config.get("way")
+ if way == 'sysfs':
+ return self.get_sysfs(config.get("loc"), config.get("flock_path"))
+ if way == "i2c":
+ bus = config.get("bus")
+ addr = config.get("addr")
+ offset = config.get("offset")
+ return self.get_i2c(bus, addr, offset)
+ if way == "io":
+ io_addr = config.get('io_addr')
+ read_len = config.get('read_len', 1)
+ return self.get_io(io_addr, read_len)
+ if way == "i2cword":
+ bus = config.get("bus")
+ addr = config.get("addr")
+ offset = config.get("offset")
+ return self.get_i2cword(bus, addr, offset)
+ if way == "devmem":
+ addr = config.get("addr")
+ digit = config.get("digit")
+ mask = config.get("mask", None)
+ return self.get_devmem(addr, digit, mask)
+ if way == "sdk":
+ get_type = config.get("type")
+ if get_type == "bcm_temp":
+ return self.getbcmtemp()
+ if get_type == "bcm_reg":
+ reg = config.get("reg")
+ return self.getbcmreg(reg)
+ raise Exception("cannot found sdk type deal")
+ if way == "devfile":
+ loc = config.get("loc")
+ offset = config.get("offset")
+ length = config.get("len")
+ ret, val_list = self.devfile_read(loc, offset, length)
+ if ret is True:
+ if length == 1:
+ val = val_list[0]
+ return True, val
+ return True, val_list
+ return False, ("devfile read failed. path:%s, offset:0x%x, read_len:%d" % (loc, offset, length))
+ if way == "devfile_ascii":
+ loc = config.get("loc")
+ offset = config.get("offset")
+ length = config.get("len")
+ return self.devfile_read_ascii(loc, offset, length)
+ if way == 'cmd':
+ cmd = config.get("cmd")
+ ret, log = self.exec_os_cmd(cmd)
+ if ret:
+ return False, ("cmd write exec %s failed, log: %s" % (cmd, log))
+ return True, log
+ if way == 'config':
+ value = config.get("value")
+ return True, value
+ raise Exception("cannot found way deal")
+
+ def devfile_read(self, loc, offset, length):
+ return osutil.readdevfile(loc, offset, length)
+
+ def devfile_read_ascii(self, loc, offset, length):
+ return osutil.readdevfile_ascii(loc, offset, length)
+
+ def get_sysfs(self, loc, flock_path=None):
+ return self.getsysfs(loc, flock_path)
+
+ def getsysfs(self, loc, flock_path=None):
+ ret, val = osutil.readsysfs(loc, flock_path)
+ return ret, val
+
+ def get_devmem(self, addr, digit, mask):
+ return osutil.getdevmem(addr, digit, mask)
+
+ def get_i2cword(self, bus, addr, offset):
+ return self.geti2cword(bus, addr, offset)
+
+ def geti2cword(self, bus, addr, offset):
+ ret, val = osutil.geti2cword(bus, addr, offset)
+ return ret, val
+
+ def get_io(self, reg_addr, read_len):
+ return self.getio(reg_addr, read_len)
+
+ def getio(self, reg_addr, read_len):
+ ret, val = osutil.io_rd(reg_addr, read_len)
+ return ret, val
+
+ def get_i2c(self, bus, addr, offset):
+ return self.geti2c(bus, addr, offset)
+
+ def geti2c(self, bus, addr, offset):
+ ret, val = osutil.wbi2cget(bus, addr, offset)
+ return ret, val
+
+ def set_value(self, config, val):
+ '''
+ get value by config way
+ way i2c/sysfs/lpc
+ '''
+ way = config.get("way")
+ if way == 'sysfs':
+ return self.set_sysfs(config.get("loc"), "0x%02x" % val)
+ if way == "i2c":
+ bus = config.get("bus")
+ addr = config.get("addr")
+ offset = config.get("offset")
+ return self.set_i2c(bus, addr, offset, val)
+ if way == "i2cpec":
+ bus = config.get("bus")
+ addr = config.get("addr")
+ offset = config.get("offset")
+ return self.seti2c_byte_pec(bus, addr, offset, val)
+ if way == 'i2cword':
+ bus = config.get("bus")
+ addr = config.get("addr")
+ offset = config.get("offset")
+ return self.set_i2cword(bus, addr, offset, val)
+ if way == "i2cwordpec":
+ bus = config.get("bus")
+ addr = config.get("addr")
+ offset = config.get("offset")
+ return self.set_i2cwordpec(bus, addr, offset, val)
+ if way == "devfile":
+ loc = config.get("loc")
+ offset = config.get("offset")
+ return self.devfile_write(loc, offset, val)
+ return False, "unsupport way: %s" % way
+
+ def set_sysfs(self, loc, value):
+ return self.setsysfs(loc, value)
+
+ def setsysfs(self, loc, value):
+ return osutil.writesysfs(loc, value)
+
+ def set_i2cword(self, bus, addr, offset, byte):
+ return self.seti2cword(bus, addr, offset, byte)
+
+ def seti2cword(self, bus, addr, offset, byte):
+ return osutil.seti2cword(bus, addr, offset, byte)
+
+ def set_i2cwordpec(self, bus, addr, offset, val):
+ return osutil.seti2cwordpec(bus, addr, offset, val)
+
+ def seti2c_byte_pec(self, bus, addr, offset, val):
+ return osutil.seti2c_byte_pec(bus, addr, offset, val)
+
+ def set_i2c(self, bus, addr, offset, byte):
+ return self.seti2c(bus, addr, offset, byte)
+
+ def seti2c(self, bus, addr, offset, byte):
+ ret, val = osutil.wbi2cset(bus, addr, offset, byte)
+ return ret, val
+
+ def devfile_write(self, loc, offset, val):
+ ret, val = osutil.writedevfile(loc, offset, val)
+ return ret, val
+
+ def getbcmtemp(self):
+ try:
+ sta, ret = osutil.getmactemp()
+ if sta is True:
+ mac_aver = float(ret.get("average", self.__error_ret))
+ mac_aver = mac_aver * 1000
+ else:
+ return False, ret
+ except AttributeError as e:
+ return False, str(e)
+ return True, mac_aver
+
+ def getbcmreg(self, reg):
+ ret, val = osutil.getsdkreg(reg)
+ return ret, val
+
+ def logger_debug(self, msg):
+ baseutil.logger_debug(msg)
+
+ def command(self, cmd):
+ ret, output = osutil.command(cmd)
+ return ret, output
+
+ def get_format_value(self, format_str):
+ ast_obj = ast.parse(format_str, mode='eval')
+ visitor = CodeVisitor()
+ visitor.visit(ast_obj)
+ ret = visitor.get_value()
+ return ret
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/fan.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/fan.py
new file mode 100644
index 000000000000..f7737ab32f51
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/fan.py
@@ -0,0 +1,417 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# fan.py
+# Python implementation of the Class fan
+#
+#######################################################
+from eepromutil.fru import ipmifru
+from eepromutil.fantlv import fan_tlv
+from plat_hal.devicebase import devicebase
+from plat_hal.rotor import rotor
+
+
+class fan(devicebase):
+ __rotor_list = []
+ __pn = None
+ __raweeprom = None
+ __sn = None
+ __hw_version = None
+ __e2loc = None
+ __rotors = None
+ __AirFlow = None
+ __SpeedMin = None
+ __SpeedMax = None
+ __PowerMax = None
+ __productName = None
+ __productSerialNumber = None
+ __WatchdogStatus = None
+ __led_attrs_config = None
+ __led_config = None
+ __WatchdogStatus_config = None
+ __AirFlowconifg = None
+ __EnableWatchdogConf = None
+ __Rotor_config = None
+ __fan_display_name = None # 'N/A'
+ __fan_display_name_conifg = None
+
+ def __init__(self, conf=None):
+ if conf is not None:
+ self.name = conf.get('name', None)
+ self.sn = conf.get('sn', None)
+ self.present = conf.get('present', None)
+ self.e2loc = conf.get('e2loc', None)
+ self.e2_type = conf.get('e2_type', "fru")
+ self.SpeedMin = conf.get('SpeedMin', None)
+ self.SpeedMax = conf.get('SpeedMax', None)
+ self.PowerMax = conf.get('PowerMax', None)
+ self.AirFlowconifg = conf.get("airflow", None)
+ self.WatchdogStatus_config = conf.get('WatchdogStatus', None)
+ self.EnableWatchdogConf = conf.get('EnableWatchdogConf', None)
+ self.led_attrs_config = conf.get('led_attrs', None)
+ self.led_config = conf.get('led', None)
+ self.Rotor_config = conf.get('Rotor', None)
+ self.fan_display_name_conifg = conf.get("fan_display_name", None)
+ rotor_tmp = []
+ for value in self.Rotor_config.values():
+ rotor_tmp.append(rotor(value))
+ rotor_tmp.sort(key=lambda x: x.name, reverse=False)
+ self.rotor_list = rotor_tmp
+ self.rotors = len(self.rotor_list)
+
+ @property
+ def EnableWatchdogConf(self):
+ return self.__EnableWatchdogConf
+
+ @EnableWatchdogConf.setter
+ def EnableWatchdogConf(self, val):
+ self.__EnableWatchdogConf = val
+
+ @property
+ def rotor_list(self):
+ return self.__rotor_list
+
+ @rotor_list.setter
+ def rotor_list(self, val):
+ self.__rotor_list = val
+
+ @property
+ def Rotor_config(self):
+ return self.__Rotor_config
+
+ @Rotor_config.setter
+ def Rotor_config(self, val):
+ self.__Rotor_config = val
+
+ @property
+ def productName(self):
+ return self.__productName
+
+ @productName.setter
+ def productName(self, val):
+ self.__productName = val
+
+ @property
+ def productSerialNumber(self):
+ return self.__productSerialNumber
+
+ @productSerialNumber.setter
+ def productSerialNumber(self, val):
+ self.__productSerialNumber = val
+
+ @property
+ def hw_version(self):
+ return self.__hw_version
+
+ @hw_version.setter
+ def hw_version(self, val):
+ self.__hw_version = val
+
+ @property
+ def sn(self):
+ return self.__sn
+
+ @sn.setter
+ def sn(self, val):
+ self.__sn = val
+
+ @property
+ def pn(self):
+ return self.__pn
+
+ @pn.setter
+ def pn(self, val):
+ self.__pn = val
+
+ @property
+ def raweeprom(self):
+ return self.__raweeprom
+
+ @raweeprom.setter
+ def raweeprom(self, val):
+ self.__raweeprom = val
+
+ @property
+ def SpeedMax(self):
+ return self.__SpeedMax
+
+ @SpeedMax.setter
+ def SpeedMax(self, val):
+ self.__SpeedMax = val
+
+ @property
+ def SpeedMin(self):
+ return self.__SpeedMin
+
+ @SpeedMin.setter
+ def SpeedMin(self, val):
+ self.__SpeedMin = val
+
+ @property
+ def PowerMax(self):
+ return self.__PowerMax
+
+ @PowerMax.setter
+ def PowerMax(self, val):
+ self.__PowerMax = val
+
+ @property
+ def rotors(self):
+ return self.__rotors
+
+ @property
+ def AirFlow(self):
+ return self.__AirFlow
+
+ @AirFlow.setter
+ def AirFlow(self, val):
+ self.__AirFlow = val
+
+ @rotors.setter
+ def rotors(self, val):
+ self.__rotors = val
+
+ @property
+ def fan_display_name_conifg(self):
+ return self.__fan_display_name_conifg
+
+ @fan_display_name_conifg.setter
+ def fan_display_name_conifg(self, val):
+ self.__fan_display_name_conifg = val
+
+ @property
+ def fan_display_name(self):
+ return self.__fan_display_name
+
+ @fan_display_name.setter
+ def fan_display_name(self, val):
+ self.__fan_display_name = val
+
+ def getspeed(self, conf):
+ tmp = None
+ if conf is None:
+ return -1
+ ret, val = self.get_value(conf)
+ if ret is True:
+ tmp = int(str(val), 10)
+ else:
+ val = None
+ if val is not None:
+ return int(15000000 / tmp)
+ return -1
+
+ def get_speed(self, rotor_index):
+ rotor_item = self.get_rotor_index(rotor_index)
+ if rotor_item is None:
+ return None
+ speed = rotor_item.rotor_Speed.Value
+ if speed is None:
+ return None
+ return int(speed)
+
+ def set_led(self, color):
+ status = self.led_attrs_config.get(color, None)
+ if status is None:
+ return False
+
+ mask = self.led_attrs_config.get('mask', 0xff)
+ ret, value = self.get_value(self.led_config)
+ if ret is False or value is None:
+ return False
+ setval = (int(value) & ~mask) | (status)
+ ret, val = self.set_value(self.led_config, setval)
+ return ret
+
+ def get_led(self):
+ mask = self.led_attrs_config.get('mask', 0xff)
+ ret, value = self.get_value(self.led_config)
+ if ret is False or value is None:
+ return False, 'N/A'
+ ledval = int(value) & mask
+ for key, val in self.led_attrs_config.items():
+ if (ledval == val) and (key != "mask"):
+ return True, key
+ return False, 'N/A'
+
+ def set_speed(self, rotor_index, level):
+ if level > 255 or level < 0:
+ return False
+ rotor_item = self.get_rotor_index(rotor_index)
+ if rotor_item is None:
+ return False
+ ret, val = self.set_value(rotor_item.Speedconfig, int(level))
+ return ret
+
+ def get_rotor_index(self, rotor_index):
+ if rotor_index > len(self.rotor_list):
+ return None
+ rotor_item = self.rotor_list[rotor_index - 1]
+ return rotor_item
+
+ def get_rotor_byname(self, rotor_index):
+ for rotor_item in self.rotor_list:
+ if rotor_item.name == rotor_index:
+ return rotor_item
+ return None
+
+ def get_presence(self):
+ ret, val = self.get_value(self.present)
+ if ret is False or val is None or val == "no_support" or val == "NA":
+ return False
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ mask = self.present.get("mask")
+ flag = value & mask
+ okval = self.present.get("okval", 0)
+ if flag == okval:
+ return True
+ return False
+
+ def get_speed_pwm(self, rotor_index):
+ rotor_item = self.get_rotor_index(rotor_index)
+ if rotor_item is None:
+ return False
+ if rotor_item.i2c_speed is None:
+ return False
+ val = round(rotor_item.i2c_speed * 100 / 255)
+ return val
+
+ def feed_watchdog(self):
+ ret = False
+ for rotor_item in self.rotor_list:
+ ret, val = rotor_item.feed_watchdog()
+ if ret is False:
+ return ret
+ return ret
+
+ def get_fru_info(self):
+ try:
+ if self.get_presence() is False:
+ raise Exception("%s: not present" % self.name)
+ eeprom = self.get_eeprom_info(self.e2loc)
+ if eeprom is None:
+ raise Exception("%s: value is none" % self.name)
+ fru = ipmifru()
+ if isinstance(eeprom, bytes):
+ eeprom = self.byteTostr(eeprom)
+ fru.decodeBin(eeprom)
+ self.productName = fru.productInfoArea.productName.strip() # PN
+ self.productSerialNumber = fru.productInfoArea.productSerialNumber.strip() # SN
+ self.hw_version = fru.productInfoArea.productVersion.strip() # HW
+ except Exception:
+ self.productName = None
+ self.productSerialNumber = None
+ self.hw_version = None
+ return False
+ return True
+
+ def get_tlv_info(self):
+ try:
+ if self.get_presence() is False:
+ raise Exception("%s: not present" % self.name)
+ eeprom = self.get_eeprom_info(self.e2loc)
+ if eeprom is None:
+ raise Exception("%s: value is none" % self.name)
+ tlv = fan_tlv()
+ rets = tlv.decode(eeprom)
+ for item in rets:
+ if item["name"] == "Product Name":
+ self.productName = item["value"].replace("\x00", "").strip()
+ elif item["name"] == "serial Number":
+ self.productSerialNumber = item["value"].replace("\x00", "").strip()
+ elif item["name"] == "hardware info":
+ self.hw_version = item["value"].replace("\x00", "").strip()
+ except Exception:
+ self.productName = None
+ self.productSerialNumber = None
+ self.hw_version = None
+ return False
+ return True
+
+ def decode_eeprom_info(self):
+ '''get fan name, hw version, sn'''
+ if self.e2_type == "fru":
+ return self.get_fru_info()
+
+ if self.e2_type == "fantlv":
+ return self.get_tlv_info()
+
+ return False
+
+ def get_AirFlow(self):
+ if self.productName is None:
+ ret = self.decode_eeprom_info()
+ if ret is False:
+ self.AirFlow = None
+ return False
+ if self.AirFlowconifg is None:
+ self.AirFlow = None
+ return False
+ for i in self.AirFlowconifg:
+ if self.productName in self.AirFlowconifg[i]:
+ self.AirFlow = i
+ return True
+ self.AirFlow = None
+ return False
+
+ def enable_watchdog(self, enable):
+ ret = False
+ if enable is True:
+ byte = self.EnableWatchdogConf.get("enable_byte", None)
+ ret, val = self.set_value(self.EnableWatchdogConf, byte)
+ elif enable is False:
+ byte = self.EnableWatchdogConf.get("disable_byte", None)
+ ret, val = self.set_value(self.EnableWatchdogConf, byte)
+ return ret
+
+ def get_watchdog_status(self):
+ dic = {"support": None, "open": None, "work_full": None, "work_allow_set": None}
+ if self.WatchdogStatus_config is None:
+ return None
+ ret, val = self.get_value(self.WatchdogStatus_config)
+ if ret is False or val is None:
+ return None
+ support_watchdog_off = self.WatchdogStatus_config.get("support_watchdog_off", None)
+ is_open_off = self.WatchdogStatus_config.get("is_open_off", None)
+ full_running_off = self.WatchdogStatus_config.get("full_running_off", None)
+ running_setting_off = self.WatchdogStatus_config.get("running_setting_off", None)
+ if support_watchdog_off is not None:
+ if support_watchdog_off & val == self.WatchdogStatus_config.get("support_watchdog_mask", None):
+ dic["support"] = True
+ else:
+ dic["support"] = False
+ return dic
+ if is_open_off is not None:
+ if is_open_off & val == self.WatchdogStatus_config.get("is_open_mask", None):
+ dic["open"] = True
+ else:
+ dic["open"] = False
+ if full_running_off is not None:
+ if full_running_off & val == self.WatchdogStatus_config.get("full_running_mask", None):
+ dic["work_full"] = True
+ else:
+ dic["work_full"] = False
+ if running_setting_off is not None:
+ if running_setting_off & val == self.WatchdogStatus_config.get("running_setting_mask", None):
+ dic["work_allow_set"] = True
+ else:
+ dic["work_allow_set"] = False
+ return dic
+
+ def get_fan_display_name(self):
+ if self.productName is None:
+ ret = self.decode_eeprom_info()
+ if ret is False:
+ self.fan_display_name = None
+ return False
+ if self.fan_display_name_conifg is None:
+ self.fan_display_name = self.productName
+ return False
+ for i in self.fan_display_name_conifg:
+ if self.productName in self.fan_display_name_conifg[i]:
+ self.fan_display_name = i
+ return True
+ self.fan_display_name = self.productName
+ return False
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/interface.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/interface.py
new file mode 100644
index 000000000000..38be03b22a25
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/interface.py
@@ -0,0 +1,1345 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# interface.py
+# Python implementation of the Class interface
+#
+#######################################################
+import collections
+from plat_hal.chassisbase import chassisbase
+from plat_hal.baseutil import baseutil
+from plat_hal.osutil import osutil
+
+
+def Singleton(cls):
+ _instance = {}
+
+ def _singleton(*args, **kargs):
+ if cls not in _instance:
+ _instance[cls] = cls(*args, **kargs)
+ return _instance[cls]
+
+ return _singleton
+
+
+@Singleton
+class interface(object):
+ __chas = None
+ __error_ret = None
+
+ def __init__(self):
+ self.chas = chassisbase()
+ self.__error_ret = -99999
+ self.__na_ret = 'N/A'
+
+ @property
+ def na_ret(self):
+ return self.__na_ret
+
+ @na_ret.setter
+ def na_ret(self, val):
+ self.__na_ret = val
+
+ @property
+ def error_ret(self):
+ return self.__error_ret
+
+ @error_ret.setter
+ def error_ret(self, val):
+ self.__error_ret = val
+
+ @property
+ def chas(self):
+ return self.__chas
+
+ @chas.setter
+ def chas(self, val):
+ self.__chas = val
+
+ # onie_e2
+ def get_onie_e2(self):
+ onie_e2_list = self.chas.onie_e2_list
+ return onie_e2_list
+
+ def get_onie_e2_path(self, name):
+ onie_e2 = self.chas.get_onie_e2_byname(name)
+ if onie_e2 is None:
+ return None
+ return onie_e2.e2_path
+
+ def get_device_airflow(self, name):
+ onie_e2 = self.chas.get_onie_e2_byname(name)
+ if onie_e2 is None:
+ return None
+ return onie_e2.airflow
+
+ def get_onie_e2_obj(self, name):
+ onie_e2 = self.chas.get_onie_e2_byname(name)
+ if onie_e2 is None:
+ return None
+ onie_e2.get_onie_e2_info()
+ return onie_e2
+
+ # temp
+ def get_temps(self):
+ templist = self.chas.temp_list
+ return templist
+
+ def get_temp_total_number(self):
+ templist = self.chas.temp_list
+ return len(templist)
+
+ def check_temp_id_exist(self, temp_id):
+ templist = self.chas.temp_list
+ for temp in templist:
+ if temp.temp_id == temp_id:
+ return True
+ return False
+
+ def get_temp_id_number(self):
+ templist = self.chas.temp_list
+ temp_num = 0
+ for i in range(len(templist)):
+ temp_id = "TEMP" + str(i + 1)
+ ret = self.check_temp_id_exist(temp_id)
+ if ret is True:
+ temp_num = temp_num + 1
+ else:
+ return temp_num
+ return temp_num
+
+ def get_temp_location(self, temp_name):
+ temp = self.chas.get_temp_byname(temp_name)
+ return temp.get_location()
+
+ def set_temp_location(self, temp_name, location):
+ temp = self.chas.get_temp_byname(temp_name)
+ return temp.set_location(location)
+
+ def set_temp_name(self, temp_name, name):
+ temp = self.chas.get_temp_byname(temp_name)
+ return temp.set_name(name)
+
+ def get_appoint_temp(self, temp_name):
+ temp = self.chas.get_led_byname(temp_name)
+ return temp.get_temp()
+
+ def set_appoint_temp(self, temp_name, val):
+ temp = self.chas.get_temp_byname(temp_name)
+ return temp.set_temp(val)
+
+ def get_temp_mintemp(self, temp_name):
+ temp = self.chas.get_temp_byname(temp_name)
+ return temp.get_mintemp()
+
+ def set_temp_mintemp(self, temp_name, val):
+ temp = self.chas.get_temp_byname(temp_name)
+ return temp.set_mintemp(val)
+
+ # led
+ def get_leds(self):
+ ledlist = self.chas.led_list
+ return ledlist
+
+ def get_led_total_number(self):
+ ledlist = self.chas.led_list
+ return len(ledlist)
+
+ def get_led_color(self, led_name):
+ led = self.chas.get_led_byname(led_name)
+ if led is None:
+ return -1
+ return led.get_color()
+
+ def get_led_color_by_type(self, led_type):
+ ledlist = self.chas.led_list
+ ledtmp = None
+ for temp in ledlist:
+ if temp.led_type == led_type:
+ ledtmp = temp
+ break
+ if ledtmp is None:
+ return -1
+ return ledtmp.get_color()
+
+ def set_led_color(self, led_name, color):
+ led = self.chas.get_led_byname(led_name)
+ if led is None:
+ return -1
+ return led.set_color(color)
+
+ # psu
+ def get_psu_total_number(self):
+ psulist = self.chas.psu_list
+ if psulist is None:
+ return -1
+ return len(psulist)
+
+ def get_psus(self):
+ psulist = self.chas.psu_list
+ return psulist
+
+ def get_psu_presence(self, psu_name):
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+ return psu.present
+
+ def get_psu_fan_number(self, psu_name):
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+ return psu.PsuFanNumber
+
+ def get_psu_fru_info(self, psu_name):
+ '''
+ {
+ "Name": "PSU1",
+ "SN": "serial_number_example", # 'N/A'
+ "PN": "part_number_example", # 'N/A'
+ "AirFlow": "B2F" # 'N/A'
+ }
+ '''
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+ psu.get_fru_info()
+ psu.get_AirFlow()
+ psu.get_psu_display_name()
+
+ dic = collections.OrderedDict()
+ dic["Name"] = psu.name
+ dic["SN"] = psu.productSerialNumber if (psu.productSerialNumber is not None) else self.na_ret
+ dic["PN"] = psu.productPartModelName if (psu.productPartModelName is not None) else self.na_ret
+ dic["DisplayName"] = psu.psu_display_name if (psu.psu_display_name is not None) else self.na_ret
+ dic["VENDOR"] = psu.productManufacturer if (psu.productManufacturer is not None) else self.na_ret
+ dic["HW"] = psu.productVersion if (psu.productVersion is not None) else self.na_ret
+ dic["AirFlow"] = psu.AirFlow if (psu.AirFlow is not None) else self.na_ret
+ return dic
+
+ def get_psu_input_output_status(self, psu_name):
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+ psu.InputsCurrent.Value # just for clear faults
+ if psu.InputStatus is True and psu.OutputStatus is True:
+ return True
+ # only has outputstatus
+ if psu.InputStatus is None and psu.OutputStatus is True:
+ return True
+ return False
+
+ def get_psu_status(self, psu_name):
+ """
+ Get status of a specific PSU
+ @return dict of the specific PSU's status, None for failure
+ Example return value(all keys are mandatory)
+ {
+ "Name": "PSU1",
+ "InputType": "DC", # "AC" or 'N/A'
+ "InputStatus": True, # H/W status bit
+ "OutputStatus": True # H/W status bit
+ "FanSpeed": {
+ "Value": 4000, # -99999
+ "Min": 2000, # -99999
+ "Max": 10000 # -99999
+ },
+ "Temperature": {
+ "Value": 40.0, # -99999.0
+ "Min": -30.0, # -99999.0
+ "Max": 50.0 # -99999.0
+ }
+ }
+ """
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+
+ if psu.get_threshold_by_model == 1:
+ psu.get_fru_info()
+
+ dic = collections.OrderedDict()
+ # psu.get_Temperature()
+ temp_dict = collections.OrderedDict()
+ temp_dict['Min'] = psu.Temperature.Min
+ temp_dict['Max'] = psu.Temperature.Max
+ temp_dict['Value'] = psu.Temperature.Value
+ temp_dict['Unit'] = psu.Temperature.Unit
+ dic["Temperature"] = temp_dict
+
+ # psu.get_FanSpeed()
+ fan_speed_dict = collections.OrderedDict()
+ fan_speed_dict['Min'] = psu.FanSpeed.Min
+ fan_speed_dict['Max'] = psu.FanSpeed.Max
+ fan_speed_dict['Tolerance'] = psu.FanSpeedTolerance
+ fan_speed_dict['Value'] = psu.FanSpeed.Value
+ fan_speed_dict['Unit'] = psu.FanSpeed.Unit
+ dic["FanSpeed"] = fan_speed_dict
+
+ dic["Name"] = psu.name
+ dic["InputType"] = psu.InputsType
+ dic["InputStatus"] = psu.InputStatus
+ dic["OutputStatus"] = psu.OutputStatus
+ dic["TempStatus"] = psu.TempStatus
+ dic["FanStatus"] = psu.FanStatus
+ return dic
+
+ def get_psu_power_status(self, psu_name):
+ """
+ Get power status of a specific PSU
+ @return dict of the specific PSU's power status, None for failure
+ Example return value
+ {
+ "Name": "PSU1",
+ "Inputs": {
+ "Status": True, # H/W status bit
+ "Type": "DC", # or "AC" or "N/A"
+ "Voltage": {
+ "Value": 220, # -1
+ "LowAlarm": 200, # -1
+ "HighAlarm": 240, # -1
+ "Unit": "V"
+ },
+ "Current": {
+ "Value": 6.0, # -99999.0
+ "LowAlarm": 0.2, # -99999.0
+ "HighAlarm": 7.0, # -99999.0
+ "Unit": "A"
+ },
+ "Power": {
+ "Value": 1000, # -99999
+ "LowAlarm": -1, # -99999
+ "HighAlarm": 1400, # -99999
+ "Unit": "W"
+ }
+ },
+ "Outputs": {
+ "Status": True,
+ "Voltage": {
+ "Value": 220,
+ "LowAlarm": 200,
+ "HighAlarm": 240,
+ "Unit": "V"
+ },
+ "Current": {
+ "Value": 6.0,
+ "LowAlarm": 0.2,
+ "HighAlarm": 7.0,
+ "Unit": "A"
+ },
+ "Power": {
+ "Value": 1000,
+ "LowAlarm": -1, # Don't care
+ "HighAlarm": 1400,
+ "Unit": "W"
+ }
+ }
+ }
+ """
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+ if psu.get_threshold_by_model == 1:
+ psu.get_fru_info()
+ dic = collections.OrderedDict()
+ inputdic = collections.OrderedDict()
+ Outputsdic = collections.OrderedDict()
+ dic["Name"] = psu.name
+ inputdic["Status"] = psu.InputStatus
+ inputdic["Type"] = psu.InputsType
+
+ # psu.get_InputsVoltage()
+ inputdic_voltage = collections.OrderedDict()
+
+ inputdic_voltage["Value"] = psu.InputsVoltage.Value
+ inputdic_voltage["LowAlarm"] = psu.InputsVoltage.Min
+ inputdic_voltage["HighAlarm"] = psu.InputsVoltage.Max
+ inputdic_voltage["Unit"] = psu.InputsVoltage.Unit
+
+ inputdic["Voltage"] = inputdic_voltage
+ inputdic_current = collections.OrderedDict()
+ inputdic_current["Value"] = psu.InputsCurrent.Value
+ inputdic_current["LowAlarm"] = psu.InputsCurrent.Min
+ inputdic_current["HighAlarm"] = psu.InputsCurrent.Max
+ inputdic_current["Unit"] = psu.InputsCurrent.Unit
+ inputdic["Current"] = inputdic_current
+
+ inputdic_power = collections.OrderedDict()
+ inputdic_power["Value"] = psu.InputsPower.Value
+ inputdic_power["LowAlarm"] = psu.InputsPower.Min
+ inputdic_power["HighAlarm"] = psu.InputsPower.Max
+ inputdic_power["Unit"] = psu.InputsPower.Unit
+ inputdic["Power"] = inputdic_power
+ Outputsdic["Status"] = psu.InputStatus
+
+ outputdic_voltage = collections.OrderedDict()
+ outputdic_current = collections.OrderedDict()
+ outputdic_power = collections.OrderedDict()
+
+ outputdic_voltage["Value"] = psu.OutputsVoltage.Value
+ outputdic_voltage["LowAlarm"] = psu.OutputsVoltage.Min
+ outputdic_voltage["HighAlarm"] = psu.OutputsVoltage.Max
+ outputdic_voltage["Unit"] = psu.OutputsVoltage.Unit
+
+ outputdic_current["Value"] = psu.OutputsCurrent.Value
+ outputdic_current["LowAlarm"] = psu.OutputsCurrent.Min
+ outputdic_current["HighAlarm"] = psu.OutputsCurrent.Max
+ outputdic_current["Unit"] = psu.OutputsCurrent.Unit
+
+ outputdic_power["Value"] = psu.OutputsPower.Value
+ outputdic_power["LowAlarm"] = psu.OutputsPower.Min
+ outputdic_power["HighAlarm"] = psu.OutputsPower.Max
+ outputdic_power["Unit"] = psu.OutputsPower.Unit
+
+ Outputsdic["Voltage"] = outputdic_voltage
+ Outputsdic["Current"] = outputdic_current
+ Outputsdic["Power"] = outputdic_power
+
+ dic["Inputs"] = inputdic
+ dic["Outputs"] = Outputsdic
+
+ return dic
+
+ def set_psu_fan_speed_pwm(self, psu_name, pwm):
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+ return psu.set_fan_speed_pwm(pwm)
+
+ def get_psu_fan_speed_pwm(self, psu_name):
+ psu = self.chas.get_psu_byname(psu_name)
+ if psu is None:
+ return -1
+ return psu.get_fan_speed_pwm()
+
+ def get_psu_info_all(self):
+ """
+ {
+ "Number": 2,
+ "PSU1": {
+ "SN": "serial_number_example", # 'N/A'
+ "PN": "part_number_example", # 'N/A'
+ "AirFlow": "intake", # 'N/A'
+
+ "FanSpeed": {
+ "Value": 4000,
+ "Min": 2000,
+ "Max": 30000
+ },
+ "Temperature": {
+ "Value": 35.0,
+ "Min": -20.0,
+ "Max": 45.0
+ },
+ "Inputs": {
+ "Status": True, # H/W status bit
+ "Type": "DC", # or "AC"
+ "Voltage": {
+ "Value": 220,
+ "LowAlarm": 200,
+ "HighAlarm": 240,
+ "Unit": "V"
+ },
+ "Current": {
+ "Value": 6.0,
+ "LowAlarm": 0.2,
+ "HighAlarm": 7.0,
+ "Unit": "A"
+ },
+ "Power": {
+ "Value": 1000,
+ "LowAlarm": -1,
+ "HighAlarm": 1400,
+ "Unit": "W"
+ }
+ },
+ "Outputs": {
+ "Status": True,
+ "Voltage": {
+ "Value": 220,
+ "LowAlarm": 200,
+ "HighAlarm": 240,
+ "Unit": "V"
+ },
+ "Current": {
+ "Value": 6.0,
+ "LowAlarm": 0.2,
+ "HighAlarm": 7.0,
+ "Unit": "A"
+ },
+ "Power": {
+ "Value": 1000,
+ "LowAlarm": -1, # Don't care
+ "HighAlarm": 1400,
+ "Unit": "W"
+ }
+ }
+ }
+ }
+ """
+
+ psus = self.get_psus()
+ psu_dict = collections.OrderedDict()
+ psu_dict['Number'] = len(psus)
+ for psu in psus:
+ dicttmp = self.get_psu_fru_info(psu.name)
+ dicttmp.update(self.get_psu_status(psu.name))
+ dicttmp.update(self.get_psu_power_status(psu.name))
+ if self.get_psu_presence(psu.name) is True:
+ dicttmp['Present'] = 'yes'
+ else:
+ dicttmp['Present'] = 'no'
+ psu_dict[psu.name] = dicttmp
+ return psu_dict
+
+ def get_fans(self):
+ fanlist = self.chas.fan_list
+ return fanlist
+
+ # fan
+ def get_fan_total_number(self):
+ fanlist = self.chas.fan_list
+ if fanlist is None:
+ return -1
+ return len(fanlist)
+
+ def get_fan_rotor_number(self, fan_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ ret = fan.rotors
+ if ret is None:
+ return -1
+ return ret
+
+ def get_fan_speed(self, fan_name, rotor_index):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ ret = fan.get_speed(rotor_index)
+ if ret is None:
+ return -1
+ return ret
+
+ def fan_speed_set_level(self, fan_name, rotor_index, level):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ ret = fan.set_speed(rotor_index, level)
+ if ret is True:
+ return 0
+ return -1
+
+ def get_fan_speed_pwm(self, fan_name, rotor_index):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ val = fan.get_speed_pwm(rotor_index)
+ if val is False:
+ return -1
+ return val
+
+ def set_fan_speed_pwm(self, fan_name, rotor_index, pwm):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ if isinstance(pwm, str):
+ rate = float(pwm.strip('%s'))
+ speed = round(rate * 255 / 100)
+ elif isinstance(pwm, int):
+ speed = round(pwm * 255 / 100)
+ elif isinstance(pwm, float):
+ speed = round(pwm * 255 / 100)
+ else:
+ return -1
+ ret = self.fan_speed_set_level(fan.name, rotor_index, speed)
+ if ret == 0:
+ return 0
+ return -1
+
+ def get_fan_watchdog_status(self):
+ fan = self.chas.fan_list[0]
+ dic = fan.get_watchdog_status()
+ if dic is None or dic["support"] is False:
+ return self.na_ret
+ if dic["open"] is False or dic["work_allow_set"] is True:
+ return "Normal"
+ if dic["work_full"] is True:
+ return "Abnormal"
+ return "Abnormal"
+
+ def enable_fan_watchdog(self, enable=True):
+ fan = self.chas.fan_list[0]
+ ret = fan.enable_watchdog(enable)
+ if ret is True:
+ return 0
+ return -1
+
+ def feed_fan_watchdog(self):
+ fan_list = self.chas.fan_list
+ if fan_list is None:
+ return -1
+ for fan in fan_list:
+ ret = fan.feed_watchdog()
+ if ret is False:
+ return -1
+ return 0
+
+ def set_fan_led(self, fan_name, color):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ ret = fan.set_led(color)
+ if ret is True:
+ return 0
+ return -1
+
+ def get_fan_led(self, fan_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return False, 'N/A'
+ return fan.get_led()
+
+ def get_fan_presence(self, fan_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ return fan.get_presence()
+
+ def get_fan_fru_info(self, fan_name):
+ """
+ Get specific fan's information
+ # Properties
+ "Name": "FAN1",
+ "SN": "serial_number_example", # 'N/A'
+ "PN": "part_number_exampple", # 'N/A'
+ "Rotors": 2, # -1
+ "AirFlow": "intake", # 'N/A'
+ "SpeedMin": 2000, # -1
+ "SpeedMax": 30000 # -1
+ """
+ fan = self.chas.get_fan_byname(fan_name)
+ fan.decode_eeprom_info()
+ fan.get_AirFlow()
+ fan.get_fan_display_name()
+
+ dic = collections.OrderedDict()
+ dic["Name"] = fan.name
+ dic["SN"] = fan.productSerialNumber
+ if dic["SN"] is None:
+ dic["SN"] = self.na_ret
+ dic["PN"] = fan.productName
+ if dic["PN"] is None:
+ dic["PN"] = self.na_ret
+ dic["DisplayName"] = fan.fan_display_name
+ if dic["DisplayName"] is None:
+ dic["DisplayName"] = self.na_ret
+
+ dic["Rotors"] = fan.rotors
+ dic["AirFlow"] = fan.AirFlow
+ if dic["AirFlow"] is None:
+ dic["AirFlow"] = self.na_ret
+ dic["SpeedMin"] = fan.SpeedMin
+ dic["SpeedMax"] = fan.SpeedMax
+ return dic
+
+ def get_fan_eeprom_info(self, fan_name):
+ """
+ Get specific fan's information
+ # Properties
+ "Name": "M6510-FAN-F", # 'N/A'
+ "SN": "serial_number_example", # 'N/A'
+ "HW": "hw_version_exampple", # 'N/A'
+ """
+ fan = self.chas.get_fan_byname(fan_name)
+ fan.decode_eeprom_info()
+ fan.get_fan_display_name()
+ dic = collections.OrderedDict()
+ dic["NAME"] = fan.productName
+ if dic["NAME"] is None:
+ dic["NAME"] = self.na_ret
+ dic["SN"] = fan.productSerialNumber
+ if dic["SN"] is None:
+ dic["SN"] = self.na_ret
+ dic["HW"] = fan.hw_version
+ if dic["HW"] is None:
+ dic["HW"] = self.na_ret
+ dic["DisplayName"] = fan.fan_display_name
+ if dic["DisplayName"] is None:
+ dic["DisplayName"] = self.na_ret
+ return dic
+
+ def get_product_fullname(self):
+ return baseutil.get_product_fullname()
+
+ def get_fan_status(self, fan_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ rotorlist = fan.rotor_list
+ dic = collections.OrderedDict()
+ for rotor in rotorlist:
+ dic_val = collections.OrderedDict()
+ if rotor.rotor_Running is True:
+ dic_val['Running'] = 'yes'
+ else:
+ dic_val['Running'] = 'no'
+ if rotor.rotor_HwAlarm is True:
+ dic_val['HwAlarm'] = 'yes'
+ else:
+ dic_val['HwAlarm'] = 'no'
+ dic_val['Speed'] = int(rotor.rotor_Speed.Value)
+ dic[rotor.name] = dic_val
+ return dic
+
+ def get_fan_rotor_status(self, fan_name, rotor_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ rotorlist = fan.rotor_list
+ for rotor in rotorlist:
+ if rotor_name == rotor.name:
+ if rotor.rotor_Running is True:
+ return True
+ return False
+ return -1
+
+ def get_fan_roll_status(self, fan_name, rotor_index):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ rotor = fan.get_rotor_index(rotor_index)
+ if rotor is None:
+ return -1
+ if rotor.rotor_Running is True:
+ return True
+ return False
+
+ def get_fan_info_fru(self, fan_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ fan.get_fru_info()
+ fan.get_AirFlow()
+ dic = collections.OrderedDict()
+ dic["Name"] = fan.name
+ dic["SN"] = fan.productSerialNumber
+ if dic["SN"] is None:
+ dic["SN"] = self.na_ret
+ dic["PN"] = fan.productPartModelName
+ if dic["PN"] is None:
+ dic["PN"] = self.na_ret
+ flag = self.get_fan_presence(fan_name)
+ if flag is True:
+ dic["Present"] = "yes"
+ elif flag is False:
+ dic["Present"] = "no"
+ else:
+ dic["Present"] = self.na_ret
+ dic["Rotors"] = fan.rotors
+ dic["AirFlow"] = fan.AirFlow
+ if dic["AirFlow"] is None:
+ dic["AirFlow"] = self.na_ret
+ return dic
+
+ # support TLV and FRU FAN E2
+ def get_fan_info(self, fan_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return None
+ fan.get_AirFlow()
+ dic = self.get_fan_eeprom_info(fan_name)
+ flag = self.get_fan_presence(fan_name)
+ if flag is True:
+ dic["Present"] = "yes"
+ elif flag is False:
+ dic["Present"] = "no"
+ else:
+ dic["Present"] = self.na_ret
+ dic["Rotors"] = fan.rotors
+ dic["AirFlow"] = fan.AirFlow
+ if dic["AirFlow"] is None:
+ dic["AirFlow"] = self.na_ret
+ dic["PowerMax"] = fan.PowerMax
+ if dic["PowerMax"] is None:
+ dic["PowerMax"] = self.na_ret
+ return dic
+
+ def get_fan_info_rotor(self, fan_name):
+ fan = self.chas.get_fan_byname(fan_name)
+ if fan is None:
+ return -1
+ rotorlist = fan.rotor_list
+ dic = collections.OrderedDict()
+ for rotor in rotorlist:
+ dic_val = collections.OrderedDict()
+ if rotor.rotor_Running is True:
+ dic_val['Running'] = 'yes'
+ else:
+ dic_val['Running'] = 'no'
+ if rotor.rotor_HwAlarm is True:
+ dic_val['HwAlarm'] = 'yes'
+ else:
+ dic_val['HwAlarm'] = 'no'
+ speed_value = rotor.rotor_Speed.Value
+ if speed_value is None:
+ dic_val['Speed'] = self.error_ret
+ else:
+ dic_val['Speed'] = int(speed_value)
+ if rotor.SpeedMin is None:
+ dic_val['SpeedMin'] = self.error_ret
+ else:
+ dic_val['SpeedMin'] = rotor.SpeedMin
+ if rotor.SpeedMax is None:
+ dic_val['SpeedMax'] = self.error_ret
+ else:
+ dic_val['SpeedMax'] = rotor.SpeedMax
+ if rotor.Tolerance is None:
+ dic_val['Tolerance'] = self.error_ret
+ else:
+ dic_val['Tolerance'] = rotor.Tolerance
+
+ dic[rotor.name] = dic_val
+ return dic
+
+ def get_fan_info_all(self):
+ fanlist = self.chas.fan_list
+ dic = collections.OrderedDict()
+ dic['Number'] = len(fanlist)
+ dic['WatchdogStatus'] = self.get_fan_watchdog_status()
+ for fan in fanlist:
+ dic[fan.name] = self.get_fan_info(fan.name)
+ dic[fan.name].update(self.get_fan_info_rotor(fan.name))
+ return dic
+
+ def temp_test(self):
+ templist = self.chas.temp_list
+ dicret = collections.OrderedDict()
+
+ for temp in templist:
+ dic = collections.OrderedDict()
+ temp_value = temp.Value
+ dic["Value"] = temp_value if (temp_value is not None) else self.error_ret
+ dic["LowAlarm"] = temp.Min
+ dic["HighAlarm"] = temp.Max
+ dicret[temp.name] = dic
+ return dicret
+
+ # dcdc
+ def get_dcdc_total_number(self):
+ dcdclist = self.chas.dcdc_list
+ if dcdclist is None:
+ return -1
+ return len(dcdclist)
+
+ def get_dcdc_by_id(self, dcdc_id):
+ dcdclist = self.chas.dcdc_list
+ dcdctmp = None
+ for dcdc in dcdclist:
+ if dcdc.dcdc_id == dcdc_id:
+ dcdctmp = dcdc
+ dic = collections.OrderedDict()
+ if dcdctmp is None:
+ dic["Name"] = self.error_ret
+ dic["Min"] = self.error_ret
+ dic["Max"] = self.error_ret
+ dic["Low"] = self.error_ret
+ dic["High"] = self.error_ret
+ dic["Value"] = self.error_ret
+ dic["Unit"] = self.error_ret
+ else:
+ dic["Name"] = dcdctmp.name
+ dic["Min"] = dcdctmp.sensor.Min
+ dic["Max"] = dcdctmp.sensor.Max
+ dic["Low"] = dcdctmp.sensor.Low
+ dic["High"] = dcdctmp.sensor.High
+ tmp = dcdctmp.sensor.Value
+ if tmp is not None:
+ dic['Value'] = tmp
+ else:
+ dic['Value'] = self.error_ret
+ dic["Unit"] = dcdctmp.sensor.Unit
+ return dic
+
+ def get_dcdc_all_info(self):
+ val_list = collections.OrderedDict()
+ dcdclist = self.chas.dcdc_list
+ for dcdc in dcdclist:
+ dicttmp = {}
+ sensorname = "%s" % (dcdc.name)
+ dicttmp['Min'] = dcdc.sensor.Min
+ dicttmp['Max'] = dcdc.sensor.Max
+ tmp = dcdc.sensor.Value
+ if tmp is not None:
+ dicttmp['Value'] = tmp
+ if tmp > dicttmp['Max'] or tmp < dicttmp['Min']:
+ dicttmp["Status"] = "NOT OK"
+ else:
+ dicttmp["Status"] = "OK"
+ else:
+ dicttmp['Value'] = self.error_ret
+ dicttmp["Status"] = "NOT OK"
+ dicttmp['Unit'] = dcdc.sensor.Unit
+ val_list[sensorname] = dicttmp
+ return val_list
+
+ # sensors
+ def get_monitor_temp(self, name):
+ templist = self.chas.temp_list
+ temptmp = None
+ for temp in templist:
+ if temp.name == name:
+ temptmp = temp
+
+ dic = collections.OrderedDict()
+ if temptmp is None:
+ dic["Min"] = self.error_ret
+ dic["Max"] = self.error_ret
+ dic["Value"] = self.error_ret
+ dic["Unit"] = self.error_ret
+ else:
+ dic["Min"] = temptmp.Min
+ dic["Max"] = temptmp.Max
+ temp_value = temptmp.Value
+ dic["Value"] = temp_value if (temp_value is not None) else self.error_ret
+ dic["Unit"] = temptmp.Unit
+ return dic
+
+ def get_monitor_temp_by_id(self, temp_id):
+ templist = self.chas.temp_list
+ temptmp = None
+ for temp in templist:
+ if temp.temp_id == temp_id:
+ temptmp = temp
+
+ dic = collections.OrderedDict()
+ if temptmp is None:
+ dic["Name"] = self.error_ret
+ dic["Api_name"] = self.error_ret
+ dic["Min"] = self.error_ret
+ dic["Max"] = self.error_ret
+ dic["Low"] = self.error_ret
+ dic["High"] = self.error_ret
+ dic["Value"] = self.error_ret
+ dic["Unit"] = self.error_ret
+ else:
+ dic["Name"] = temptmp.name
+ dic["Api_name"] = temptmp.api_name
+ dic["Min"] = temptmp.Min
+ dic["Max"] = temptmp.Max
+ dic["Low"] = temptmp.Low
+ dic["High"] = temptmp.High
+ temp_value = temptmp.Value
+ dic["Value"] = temp_value if (temp_value is not None) else self.error_ret
+ dic["Unit"] = temptmp.Unit
+ return dic
+
+ def get_temp_info(self):
+ val_list = collections.OrderedDict()
+ # temp
+ templist = self.chas.temp_list
+ for temp in templist:
+ dic = collections.OrderedDict()
+ dic["Min"] = temp.Min
+ dic["Max"] = temp.Max
+ dic["Low"] = temp.Low
+ dic["High"] = temp.High
+ temp_value = temp.Value
+ dic["Value"] = temp_value if (temp_value is not None) else self.error_ret
+ dic["Unit"] = temp.Unit
+ val_list[temp.name] = dic
+ return val_list
+
+ def get_sensor_info(self):
+ val_list = collections.OrderedDict()
+ # temp
+ templist = self.chas.temp_list
+ for temp in templist:
+ dic = collections.OrderedDict()
+ dic["Min"] = temp.Min
+ dic["Max"] = temp.Max
+ dic["Low"] = temp.Low
+ dic["High"] = temp.High
+ temp_value = temp.Value
+ dic["Value"] = temp_value if (temp_value is not None) else self.error_ret
+ dic["Unit"] = temp.Unit
+ val_list[temp.name] = dic
+ # fan
+ fanlist = self.chas.fan_list
+ for fan in fanlist:
+ for rotor in fan.rotor_list:
+ sensorname = "%s%s" % (fan.name, rotor.name)
+ speed = collections.OrderedDict()
+ speed['Min'] = rotor.rotor_Speed.Min
+ speed['Max'] = rotor.rotor_Speed.Max
+ rotor_speed_Value = rotor.rotor_Speed.Value
+ speed['Value'] = rotor_speed_Value if (rotor_speed_Value is not None) else self.error_ret
+ speed['Unit'] = rotor.rotor_Speed.Unit
+ val_list[sensorname] = speed
+
+ val_list.update(self.get_dcdc_all_info())
+
+ # psu
+ psulist = self.chas.psu_list
+ for psu in psulist:
+ inputdic_voltage = collections.OrderedDict()
+ inputdic_current = collections.OrderedDict()
+ inputdic_power = collections.OrderedDict()
+ outputdic_voltage = collections.OrderedDict()
+ outputdic_current = collections.OrderedDict()
+ outputdic_power = collections.OrderedDict()
+ temperature = collections.OrderedDict()
+ fanspeed = collections.OrderedDict()
+
+ psu_temp_value = psu.Temperature.Value
+ temperature["Value"] = psu_temp_value if (psu_temp_value is not None) else self.error_ret
+ temperature["Min"] = psu.Temperature.Min
+ temperature["Max"] = psu.Temperature.Max
+ temperature["Unit"] = psu.Temperature.Unit
+
+ fanspeed["Value"] = psu.FanSpeed.Value
+ fanspeed["Min"] = psu.FanSpeed.Min
+ fanspeed["Max"] = psu.FanSpeed.Max
+ fanspeed["Unit"] = psu.FanSpeed.Unit
+
+ psu_inputvoltage_value = psu.InputsVoltage.Value
+ inputdic_voltage["Value"] = psu_inputvoltage_value if (
+ psu_inputvoltage_value is not None) else self.error_ret
+ inputdic_voltage["Min"] = psu.InputsVoltage.Min
+ inputdic_voltage["Max"] = psu.InputsVoltage.Max
+ inputdic_voltage["Unit"] = psu.InputsVoltage.Unit
+
+ psu_inputcurrent_value = psu.InputsCurrent.Value
+ inputdic_current["Value"] = psu_inputcurrent_value if (
+ psu_inputcurrent_value is not None) else self.error_ret
+ inputdic_current["Min"] = psu.InputsCurrent.Min
+ inputdic_current["Max"] = psu.InputsCurrent.Max
+ inputdic_current["Unit"] = psu.InputsCurrent.Unit
+
+ psu_inputpower_value = psu.InputsPower.Value
+ inputdic_power["Value"] = psu_inputpower_value if (psu_inputpower_value is not None) else self.error_ret
+ inputdic_power["Min"] = psu.InputsPower.Min
+ inputdic_power["Max"] = psu.InputsPower.Max
+ inputdic_power["Unit"] = psu.InputsPower.Unit
+
+ psu_outputvoltage_value = psu.OutputsVoltage.Value
+ outputdic_voltage["Value"] = psu_outputvoltage_value if (
+ psu_outputvoltage_value is not None) else self.error_ret
+ outputdic_voltage["Min"] = psu.OutputsVoltage.Min
+ outputdic_voltage["Max"] = psu.OutputsVoltage.Max
+ outputdic_voltage["Unit"] = psu.OutputsVoltage.Unit
+
+ psu_outputcurrent_value = psu.OutputsCurrent.Value
+ outputdic_current["Value"] = psu_outputcurrent_value if (
+ psu_outputcurrent_value is not None) else self.error_ret
+ outputdic_current["Min"] = psu.OutputsCurrent.Min
+ outputdic_current["Max"] = psu.OutputsCurrent.Max
+ outputdic_current["Unit"] = psu.OutputsCurrent.Unit
+
+ psu_outputpower_value = psu.OutputsPower.Value
+ outputdic_power["Value"] = psu_outputpower_value if (
+ psu_outputpower_value is not None) else self.error_ret
+ outputdic_power["Min"] = psu.OutputsPower.Min
+ outputdic_power["Max"] = psu.OutputsPower.Max
+ outputdic_power["Unit"] = psu.OutputsPower.Unit
+
+ val_list["%s%s" % (psu.name, "Vol_I")] = inputdic_voltage
+ val_list["%s%s" % (psu.name, "Curr_I")] = inputdic_current
+ val_list["%s%s" % (psu.name, "Power_I")] = inputdic_power
+ val_list["%s%s" % (psu.name, "Vol_O")] = outputdic_voltage
+ val_list["%s%s" % (psu.name, "Curr_O")] = outputdic_current
+ val_list["%s%s" % (psu.name, "Power_O")] = outputdic_power
+ val_list["%s%s" % (psu.name, "Fan")] = fanspeed
+ val_list["%s%s" % (psu.name, "Temp")] = temperature
+
+ return val_list
+
+ # cpld
+ def get_cpld_total_number(self):
+ cpldlist = self.chas.cpld_list
+ return len(cpldlist)
+
+ def get_cpld_user_reg(self):
+ cpld = self.chas.get_cpld_byname("BASE_CPLD")
+ if cpld is None:
+ return None
+ return cpld.get_user_reg()
+
+ def set_cpld_user_reg(self, value):
+ if isinstance(value, int) is False:
+ baseutil.logger_debug("value must int %s" % type(value))
+ return -1
+ if (int(value) < 0 or int(value) > 255):
+ baseutil.logger_debug("value must [0 - 255]")
+ return -1
+ cpld = self.chas.get_cpld_byname("BASE_CPLD")
+ if cpld is None:
+ baseutil.logger_debug("name BASE_CPLD not find")
+ return -1
+ if cpld.set_user_reg(value) is True:
+ return 0
+ return -1
+
+ def set_cpld_console_owner(self, owner):
+ """
+ Set console I/O owner
+
+ @param owner I/O owner of the console, either "cpu" or "bmc"
+
+ @return 0 for success, -1 for failure
+ """
+ if owner is None:
+ baseutil.logger_debug("owner is None")
+ return -1
+ owner_tuple = ("cpu", "bmc")
+ if owner not in owner_tuple:
+ baseutil.logger_debug("owner is %s, must cpu or bmc" % owner)
+ return -1
+ cpld = self.chas.get_cpld_byname("BASE_CPLD")
+ if cpld is None:
+ baseutil.logger_debug("name BASE_CPLD not find")
+ return -1
+ if cpld.set_console_owner(owner) is True:
+ return 0
+ return -1
+
+ def get_cpld_version_by_id(self, cpld_id):
+ cpldlist = self.chas.cpld_list
+ cpldtmp = None
+ for cpld in cpldlist:
+ if cpld.cpld_id == cpld_id:
+ cpldtmp = cpld
+
+ dic = collections.OrderedDict()
+ if cpldtmp is None:
+ dic["Name"] = self.na_ret
+ dic["Version"] = self.na_ret
+ dic["Desc"] = self.na_ret
+ dic["Slot"] = None
+ dic["Warm"] = None
+ else:
+ dic["Name"] = cpldtmp.name
+ dic["Version"] = cpldtmp.get_version()
+ dic["Desc"] = cpldtmp.desc
+ dic["Slot"] = cpldtmp.slot
+ dic["Warm"] = cpldtmp.warm
+ return dic
+
+ def get_cpld_all_version(self):
+ """
+ Get version of all CPLDs' that can be read from BMC
+
+ @return dict of CPLDs' version or None for failure.
+ example outputs:
+ {
+ "BASE_CPLD": "0.1", # or "N/A" for read failure
+ "FAN_CPLD": "0.2"
+ }
+ """
+ cpld_version = {
+ "BASE_CPLD": "N/A",
+ "FAN_CPLD": "N/A"
+ }
+ for cpld_name in cpld_version:
+ cpld = self.chas.get_cpld_byname(cpld_name)
+ if cpld is None:
+ baseutil.logger_debug("name %s not find" % cpld_name)
+ continue
+ cpld_version[cpld_name] = cpld.get_version()
+ return cpld_version
+
+ # comp
+ def get_comp_total_number(self):
+ complist = self.chas.comp_list
+ return len(complist)
+
+ def get_comp_list(self):
+ return self.chas.comp_list
+
+ def get_comp_id(self, comp):
+ return comp.comp_id
+
+ def get_comp_version_by_id(self, comp_id):
+ comp_list = self.chas.comp_list
+ comptmp = None
+ for comp in comp_list:
+ if comp.comp_id == comp_id:
+ comptmp = comp
+ break
+
+ dic = collections.OrderedDict()
+ if comptmp is None:
+ dic["Name"] = self.na_ret
+ dic["Version"] = self.na_ret
+ dic["Desc"] = self.na_ret
+ dic["Slot"] = None
+ else:
+ dic["Name"] = comptmp.name
+ dic["Version"] = comptmp.get_version()
+ dic["Desc"] = comptmp.desc
+ dic["Slot"] = comptmp.slot
+ return dic
+
+ def get_bmc_productname(self):
+ """
+ Get product name
+
+ @return product name string, e.g. $(device name)-F-$(VENDOR_NAME), if error return "N/A"
+ """
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ baseutil.logger_debug("name bmc(master) not find")
+ return self.na_ret
+ return bmc.get_productname()
+
+ def call_bmc_diagcmd(self, cmdstr):
+ """
+ Call BMC diag comman func
+
+ @return ret: 0 sucess , -1 fail
+ outmsg: if success is out msg, or fail is err msg
+ """
+ if (cmdstr is None or cmdstr == ""):
+ outmsg = "cmdstr is empty"
+ baseutil.logger_debug(outmsg)
+ return -1, outmsg
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ outmsg = "name bmc(master) not find"
+ baseutil.logger_debug(outmsg)
+ return -1, outmsg
+ baseutil.logger_debug("call cmdstr %s" % cmdstr)
+ return bmc.call_diagcmd(cmdstr)
+
+ def write_bios_version(self, flash, version):
+ bios = self.chas.get_bios_byname("master")
+ if bios is None:
+ baseutil.logger_debug("name bios(master) not find")
+ return -1
+ return bios.set_bios_version(flash, version)
+
+ def get_bios_version(self):
+ bios = self.chas.get_bios_byname("master")
+ if bios is None:
+ baseutil.logger_debug("name bios(master) not find")
+ return -1
+ return bios.get_bios_version()
+
+ def get_bios_status(self):
+ bios = self.chas.get_bios_byname("master")
+ if bios is None:
+ baseutil.logger_debug("name bios(master) not find")
+ return -1
+ return bios.get_bios_boot_status()
+
+ def get_bmc_mac_rov(self):
+ """
+ Get BMC mac rov
+
+ @return ret: 0 sucess , -1 fail
+ outmsg: if success is out msg, or fail is err msg
+ """
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ msg = "name master not find"
+ baseutil.logger_debug(msg)
+ return -1, msg
+ return bmc.get_mac_rov()
+
+ def get_bmc_next_boot(self):
+ """
+ Get next booting flash of BMC
+
+ @return 'master'/'slave' on success, "N/A" for failure
+ """
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ baseutil.logger_debug("name master not find")
+ return self.na_ret
+ return bmc.get_next_boot()
+
+ def set_bmc_next_boot(self, flash):
+ """
+ Set flash from which next BMC boot
+
+ @param flash Booting flash of BMC, "master" or "slave"
+
+ @return 0 on success, -1 for failure
+ """
+ flash_status = ("master", "slave")
+ if flash is None or flash not in flash_status:
+ baseutil.logger_debug("parameter flash illegal, should be [master|slave]")
+ return -1
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ baseutil.logger_debug("name master not find")
+ return -1
+ return bmc.set_next_boot(flash)
+
+ def reboot_bmc(self):
+ """
+ Reboot running BMC
+ """
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ baseutil.logger_debug("name master not find")
+ return -1
+ return bmc.reboot()
+
+ def get_bmc_info(self):
+ """
+ Get BMC info
+
+ @return dict of BMC info or None for failure
+ "Version": "1.1.1", # "N/A"
+ "Flash": "master", # "N/A"
+ "Next": "master" # "N/A"
+ """
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ baseutil.logger_debug("name master not find")
+ return self.na_ret
+ return bmc.get_info()
+
+ def get_bmc_version_all(self):
+ """
+ @return dict of BMCs
+ {
+ "MasterVersion": "1.1.1", # "N/A"
+ "SlaveVersion": "1.1.1" # "N/A"
+ }
+ """
+ bmc = self.chas.get_bmc_byname("master")
+ if bmc is None:
+ baseutil.logger_debug("name master not find")
+ return self.na_ret
+ return bmc.get_version_all()
+
+ def bmc_execute_command(self, cmd_str):
+ ret, output = osutil.command(cmd_str)
+ if ret:
+ baseutil.logger_debug("execute %s command failed" % (cmd_str))
+ return ret, output
+
+ def get_cpu_reset_num(self):
+ """
+ Get CPU reset num
+ @return CPU reset num on success, -1 for failure
+ """
+ cpu = self.chas.get_cpu_byname("cpu")
+ if cpu is None:
+ msg = "name cpu not find"
+ baseutil.logger_debug(msg)
+ return -1
+ return cpu.get_cpu_reset_num()
+
+ def get_cpu_reboot_cause(self):
+ """
+ Get CPU reboot cause
+ @return string of cpu reboot reason
+ """
+ cpu = self.chas.get_cpu_byname("cpu")
+ if cpu is None:
+ msg = "name cpu not find"
+ baseutil.logger_debug(msg)
+ return "Unknown reboot cause"
+ return cpu.get_cpu_reboot_cause()
+
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/led.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/led.py
new file mode 100644
index 000000000000..7fb869c74d7f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/led.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# led.py
+# Python implementation of the Class led
+#
+#######################################################
+from plat_hal.devicebase import devicebase
+
+
+class led(devicebase):
+ def __init__(self, conf=None):
+ if conf is not None:
+ self.name = conf.get('name', None)
+ self.led_type = conf.get('led_type', None)
+ self.led_attrs_config = conf.get('led_attrs', None)
+ self.led_config = conf.get('led', None)
+
+ def set_color(self, color):
+ status = self.led_attrs_config.get(color, None)
+ if status is None:
+ return False
+
+ mask = self.led_attrs_config.get('mask', 0xff)
+
+ if isinstance(self.led_config, list):
+ for led_config_index in self.led_config:
+ ret, value = self.get_value(led_config_index)
+ if (ret is False) or (value is None):
+ return False
+ setval = (int(value) & ~mask) | (status)
+ ret, val = self.set_value(led_config_index, setval)
+ if ret is False:
+ return ret
+ else:
+ ret, value = self.get_value(self.led_config)
+ if (ret is False) or (value is None):
+ return False
+ setval = (int(value) & ~mask) | (status)
+ ret, val = self.set_value(self.led_config, setval)
+ return ret
+
+ def get_color(self):
+ mask = self.led_attrs_config.get('mask', 0xff)
+ ret, value = self.get_value(self.led_config)
+ if ret is False or value is None:
+ return False, 'N/A'
+ ledval = int(value) & mask
+ for key, val in self.led_attrs_config.items():
+ if (ledval == val) and (key != "mask"):
+ return True, key
+ return False, 'N/A'
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/onie_e2.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/onie_e2.py
new file mode 100644
index 000000000000..9ac32cace263
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/onie_e2.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# onie_e2.py
+# Python implementation of the Class onie_e2
+#
+#######################################################
+from plat_hal.devicebase import devicebase
+from eepromutil.onietlv import onie_tlv
+
+
+class onie_e2(devicebase):
+
+ def __init__(self, conf=None):
+ self._cardid = ""
+ self._productname = ""
+ self._partnum = ""
+ self._serialnum = ""
+ self._macbase = ""
+ self._manufdate = ""
+ self._deviceversion = ""
+ self._labelrevision = ""
+ self._platformname = ""
+ self._onieversion = ""
+ self._macsize = ""
+ self._manufname = ""
+ self._manufcountry = ""
+ self._vendorname = ""
+ self._diagname = ""
+ self._servicetag = ""
+
+ if conf is not None:
+ self.name = conf.get('name', None)
+ self.e2loc = conf.get('e2loc', None)
+ self.e2_path = self.e2loc.get('loc', None)
+ self.airflow = conf.get('airflow', "intake")
+
+ @property
+ def cardid(self):
+ return self._cardid
+
+ @property
+ def productname(self):
+ return self._productname
+
+ @property
+ def partnum(self):
+ return self._partnum
+
+ @property
+ def serialnum(self):
+ return self._serialnum
+
+ @property
+ def macbase(self):
+ return self._macbase
+
+ @property
+ def manufdate(self):
+ return self._manufdate
+
+ @property
+ def deviceversion(self):
+ return self._deviceversion
+
+ @property
+ def labelrevision(self):
+ return self._labelrevision
+
+ @property
+ def platformname(self):
+ return self._platformname
+
+ @property
+ def onieversion(self):
+ return self._onieversion
+
+ @property
+ def macsize(self):
+ return self._macsize
+
+ @property
+ def manufname(self):
+ return self._manufname
+
+ @property
+ def manufcountry(self):
+ return self._manufcountry
+
+ @property
+ def vendorname(self):
+ return self._vendorname
+
+ @property
+ def diagname(self):
+ return self._diagname
+
+ @property
+ def servicetag(self):
+ return self._servicetag
+
+ def get_onie_e2_info(self):
+ try:
+ eeprom = self.get_eeprom_info(self.e2loc)
+ if eeprom is None:
+ raise Exception("%s: value is none" % self.name)
+ onietlv = onie_tlv()
+ onietlv.decode(eeprom)
+ self._cardid = onietlv.cardid
+ self._productname = onietlv.productname
+ self._partnum = onietlv.partnum
+ self._serialnum = onietlv.serialnum
+ self._macbase = onietlv.macbase
+ self._manufdate = onietlv.manufdate
+ self._deviceversion = onietlv.deviceversion
+ self._labelrevision = onietlv.labelrevision
+ self._platformname = onietlv.platformname
+ self._onieversion = onietlv.onieversion
+ self._macsize = onietlv.macsize
+ self._manufname = onietlv.manufname
+ self._manufcountry = onietlv.manufcountry
+ self._vendorname = onietlv.vendorname
+ self._diagname = onietlv.diagname
+ self._servicetag = onietlv.servicetag
+ except Exception:
+ return False
+ return True
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/osutil.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/osutil.py
new file mode 100644
index 000000000000..684e26bb9ecd
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/osutil.py
@@ -0,0 +1,440 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# osutil.py
+# Python implementation of the Class osutil
+#
+#######################################################
+
+import os
+import glob
+import re
+import time
+import subprocess
+import fcntl
+import syslog
+from functools import wraps
+from wbutil.smbus import SMBus
+
+
+PLATFORM_HAL_DEBUG_FILE = "/etc/.platform_hal_debug_flag"
+
+
+def platform_hal_debug(s):
+ if os.path.exists(PLATFORM_HAL_DEBUG_FILE):
+ syslog.openlog("PLATFORM_HAL", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_DEBUG, s)
+
+
+def retry(maxretry=6, delay=0.01):
+ '''
+ maxretry: max retry times
+ delay : interval after last retry
+ '''
+ def decorator(f):
+ @wraps(f)
+ def wrapper(*args, **kwargs):
+ time_retry = maxretry
+ time_delay = delay
+ result_msg = ""
+ while time_retry:
+ try:
+ val, result_msg = f(*args, **kwargs)
+ if val is True:
+ return val, result_msg
+ time_retry -= 1
+ time.sleep(time_delay)
+ except Exception as e:
+ time_retry -= 1
+ result_msg = str(e)
+ time.sleep(time_delay)
+ return False, "max time retry last errmsg is {}".format(result_msg)
+ return wrapper
+ return decorator
+
+
+pidfile = None
+
+
+def file_rw_lock(file_path):
+ global pidfile
+ pidfile = open(file_path, "r")
+ try:
+ fcntl.flock(pidfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ platform_hal_debug("file_rw_lock success")
+ return True
+ except Exception:
+ if pidfile is not None:
+ pidfile.close()
+ pidfile = None
+ return False
+
+
+def file_rw_unlock():
+ try:
+ global pidfile
+
+ if pidfile is not None:
+ fcntl.flock(pidfile, fcntl.LOCK_UN)
+ pidfile.close()
+ pidfile = None
+ platform_hal_debug("file_rw_unlock success")
+ else:
+ platform_hal_debug("pidfile is invalid, do nothing")
+ return True
+ except Exception as e:
+ platform_hal_debug("file_rw_unlock err, msg: %s" % (str(e)))
+ return False
+
+
+def take_file_rw_lock(file_path):
+ loop = 1000
+ ret = False
+ for i in range(0, loop):
+ ret = file_rw_lock(file_path)
+ if ret is True:
+ break
+ time.sleep(0.001)
+ return ret
+
+
+class osutil(object):
+ """
+ osutil
+ """
+
+ @staticmethod
+ @retry(maxretry=6)
+ def wbi2cget_python(bus, addr, reg):
+ with SMBus(bus) as y:
+ val, ind = y.read_byte_data(addr, reg, True)
+ return val, ind
+
+ @staticmethod
+ @retry(maxretry=6)
+ def wbi2cset_python(bus, addr, reg, value):
+ with SMBus(bus) as y:
+ val, ind = y.write_byte_data(addr, reg, value, True)
+ return val, ind
+
+ @staticmethod
+ @retry(maxretry=6)
+ def wbi2cgetword_python(bus, addr, reg):
+ with SMBus(bus) as y:
+ val, ind = y.read_word_data(addr, reg, True)
+ return val, ind
+
+ @staticmethod
+ @retry(maxretry=6)
+ def wbi2csetword_python(bus, addr, reg, value):
+ with SMBus(bus) as y:
+ val, ind = y.write_word_data(addr, reg, value, True)
+ return val, ind
+
+ @staticmethod
+ @retry(maxretry=6)
+ def wbi2csetwordpec_python(bus, addr, reg, value):
+ with SMBus(bus) as y:
+ val, ind = y.write_word_data_pec(addr, reg, value, True)
+ return val, ind
+
+ @staticmethod
+ @retry(maxretry=6)
+ def wbi2cset_byte_pec_python(bus, addr, reg, value):
+ with SMBus(bus) as y:
+ val, ind = y.write_byte_data_pec(addr, reg, value, True)
+ return val, ind
+
+ @staticmethod
+ def command(cmdstr):
+ retcode, output = subprocess.getstatusoutput(cmdstr)
+ return retcode, output
+
+ @staticmethod
+ def geti2cword_i2ctool(bus, addr, offset):
+ command_line = "i2cget -f -y %d 0x%02x 0x%02x wp" % (bus, addr, offset)
+ retrytime = 6
+ ret_t = ""
+ for i in range(retrytime):
+ ret, ret_t = osutil.command(command_line)
+ if ret == 0:
+ return True, int(ret_t, 16)
+ time.sleep(0.1)
+ return False, ret_t
+
+ @staticmethod
+ def seti2cword_i2ctool(bus, addr, offset, val):
+ command_line = "i2cset -f -y %d 0x%02x 0x%0x 0x%04x wp" % (bus, addr, offset, val)
+ retrytime = 6
+ ret_t = ""
+ for i in range(retrytime):
+ ret, ret_t = osutil.command(command_line)
+ if ret == 0:
+ return True, ret_t
+ time.sleep(0.1)
+ return False, ret_t
+
+ @staticmethod
+ def wbi2cget_i2ctool(bus, devno, address):
+ command_line = "i2cget -f -y %d 0x%02x 0x%02x " % (bus, devno, address)
+ retrytime = 6
+ ret_t = ""
+ for i in range(retrytime):
+ ret, ret_t = osutil.command(command_line)
+ if ret == 0:
+ return True, int(ret_t, 16)
+ time.sleep(0.1)
+ return False, ret_t
+
+ @staticmethod
+ def wbi2cset_i2ctool(bus, devno, address, byte):
+ command_line = "i2cset -f -y %d 0x%02x 0x%02x 0x%02x" % (
+ bus, devno, address, byte)
+ retrytime = 6
+ ret_t = ""
+ for i in range(retrytime):
+ ret, ret_t = osutil.command(command_line)
+ if ret == 0:
+ return True, ret_t
+ return False, ret_t
+
+ @staticmethod
+ def geti2cword(bus, addr, offset):
+ return osutil.wbi2cgetword_python(bus, addr, offset)
+
+ @staticmethod
+ def seti2cword(bus, addr, offset, val):
+ return osutil.wbi2csetword_python(bus, addr, offset, val)
+
+ @staticmethod
+ def seti2cwordpec(bus, addr, offset, val):
+ return osutil.wbi2csetwordpec_python(bus, addr, offset, val)
+
+ @staticmethod
+ def seti2c_byte_pec(bus, addr, offset, val):
+ return osutil.wbi2cset_byte_pec_python(bus, addr, offset, val)
+
+ @staticmethod
+ def wbi2cget(bus, devno, address):
+ return osutil.wbi2cget_python(bus, devno, address)
+
+ @staticmethod
+ def wbi2cset(bus, devno, address, byte):
+ return osutil.wbi2cset_python(bus, devno, address, byte)
+
+ @staticmethod
+ def byteTostr(val):
+ strtmp = ''
+ for value in val:
+ strtmp += chr(value)
+ return strtmp
+
+ @staticmethod
+ def io_rd(reg_addr, read_len=1):
+ try:
+ regaddr = 0
+ if isinstance(reg_addr, int):
+ regaddr = reg_addr
+ else:
+ regaddr = int(reg_addr, 16)
+ devfile = "/dev/port"
+ fd = os.open(devfile, os.O_RDWR | os.O_CREAT)
+ os.lseek(fd, regaddr, os.SEEK_SET)
+ val = os.read(fd, read_len)
+ return True, "".join(["%02x" % item for item in val])
+ except ValueError as e:
+ return False, str(e)
+ except Exception as e:
+ return False, str(e)
+ finally:
+ os.close(fd)
+
+ @staticmethod
+ def readsysfs(location, flock_path=None):
+ flock_path_tmp = None
+ platform_hal_debug("readsysfs, location:%s, flock_path:%s" % (location, flock_path))
+ try:
+ if flock_path is not None:
+ flock_paths = glob.glob(flock_path)
+ if len(flock_paths) != 0:
+ flock_path_tmp = flock_paths[0]
+ platform_hal_debug("try to get file lock, path:%s" % flock_path_tmp)
+ ret = take_file_rw_lock(flock_path_tmp)
+ if ret is False:
+ platform_hal_debug("take file lock timeout, path:%s" % flock_path_tmp)
+ return False, ("take file rw lock timeout, path:%s" % flock_path_tmp)
+ else:
+ platform_hal_debug("config error, can't find flock_path:%s" % flock_path)
+
+ locations = glob.glob(location)
+ with open(locations[0], 'rb') as fd1:
+ retval = fd1.read()
+ retval = osutil.byteTostr(retval)
+ if flock_path_tmp is not None:
+ file_rw_unlock()
+
+ retval = retval.rstrip('\r\n')
+ retval = retval.lstrip(" ")
+ except Exception as e:
+ if flock_path_tmp is not None:
+ file_rw_unlock()
+ platform_hal_debug("readsysfs error, msg:%s" % str(e))
+ return False, (str(e) + " location[%s]" % location)
+ return True, retval
+
+ @staticmethod
+ def writesysfs(location, value):
+ try:
+ if not os.path.isfile(location):
+ print(location, 'not found !')
+ return False, ("location[%s] not found !" % location)
+ with open(location, 'w') as fd1:
+ fd1.write(value)
+ except Exception as e:
+ return False, (str(e) + " location[%s]" % location)
+ return True, ("set location[%s] %s success !" % (location, value))
+
+ @staticmethod
+ def getdevmem(addr, digit, mask):
+ command_line = "devmem 0x%02x %d" % (addr, digit)
+ retrytime = 6
+ ret_t = ""
+ for i in range(retrytime):
+ ret, ret_t = osutil.command(command_line)
+ if ret == 0:
+ if mask is not None:
+ ret_t = str(int(ret_t, 16) & mask)
+ return True, ret_t
+ return False, ret_t
+
+ @staticmethod
+ def readdevfile_ascii(path, offset, length):
+ msg = ""
+ ret = ""
+ joinstr = ''
+ fd = -1
+
+ if not os.path.exists(path):
+ msg = path + " not found !"
+ return False, msg
+
+ try:
+ fd = os.open(path, os.O_RDONLY)
+ os.lseek(fd, offset, os.SEEK_SET)
+ ret = os.read(fd, length)
+ for item in ret:
+ joinstr += '%02x ' % item # like sysfs, display in hex
+ except Exception as e:
+ msg = str(e)
+ return False, msg
+ finally:
+ if fd > 0:
+ os.close(fd)
+ return True, joinstr
+
+ @staticmethod
+ def readdevfile(path, offset, length):
+ msg = ""
+ ret = ""
+ fd = -1
+ val_list = []
+
+ if not os.path.exists(path):
+ msg = path + " not found !"
+ return False, msg
+
+ try:
+ fd = os.open(path, os.O_RDONLY)
+ os.lseek(fd, offset, os.SEEK_SET)
+ ret = os.read(fd, length)
+ for item in ret:
+ val_list.append(item)
+ except Exception as e:
+ msg = str(e)
+ return False, msg
+ finally:
+ if fd > 0:
+ os.close(fd)
+ return True, val_list
+
+ @staticmethod
+ def writedevfile(path, offset, buf):
+ msg = ""
+ fd = -1
+
+ if not os.path.exists(path):
+ msg = path + " not found !"
+ return False, msg
+
+ if isinstance(buf, list):
+ if len(buf) == 0:
+ msg = "buf:%s is NONE !" % buf
+ return False, msg
+ elif isinstance(buf, int):
+ buf = [buf]
+ else:
+ msg = "buf:%s is not list type or not int type !" % buf
+ return False, msg
+
+ try:
+ fd = os.open(path, os.O_WRONLY)
+ os.lseek(fd, offset, os.SEEK_SET)
+ ret = os.write(fd, bytes(buf))
+ except Exception as e:
+ msg = str(e)
+ return False, msg
+ finally:
+ if fd > 0:
+ os.close(fd)
+
+ return True, ret
+
+ @staticmethod
+ def wb_os_system(cmd):
+ status, output = subprocess.getstatusoutput(cmd)
+ return status, output
+
+ @staticmethod
+ def getsdkreg(reg):
+ try:
+ cmd = "bcmcmd -t 1 'getr %s ' < /dev/null" % reg
+ ret, result = osutil.wb_os_system(cmd)
+ result_t = result.strip().replace("\r", "").replace("\n", "")
+ if ret != 0 or "Error:" in result_t:
+ return False, result
+ patt = r"%s.(.*):(.*)>drivshell" % reg
+ rt = re.findall(patt, result_t, re.S)
+ test = re.findall("=(.*)", rt[0][0])[0]
+ except Exception as e:
+ return False, 'get sdk register error, msg: %s' % str(e)
+ return True, test
+
+ @staticmethod
+ def getmactemp():
+ try:
+ result = {}
+ # need to exec twice
+ osutil.wb_os_system("bcmcmd -t 1 \"show temp\" < /dev/null")
+ ret, log = osutil.wb_os_system("bcmcmd -t 1 \"show temp\" < /dev/null")
+ if ret:
+ return False, result
+ logs = log.splitlines()
+ for line in logs:
+ if "average" in line:
+ b = re.findall(r'\d+.\d+', line)
+ result["average"] = b[0]
+ elif "maximum" in line:
+ b = re.findall(r'\d+.\d+', line)
+ result["maximum"] = b[0]
+ except Exception as e:
+ return False, str(e)
+ return True, result
+
+ @staticmethod
+ def std_match(stdout, pattern):
+ if pattern is None:
+ return stdout.strip()
+ for line in stdout.splitlines():
+ if re.match(pattern, line):
+ return line.strip()
+ return None
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/psu.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/psu.py
new file mode 100644
index 000000000000..a5a4fea1792b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/psu.py
@@ -0,0 +1,711 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# psu.py
+# Python implementation of the Class psu
+#
+#######################################################
+from eepromutil.fru import ipmifru
+from eepromutil.cust_fru import CustFru
+from plat_hal.devicebase import devicebase
+from plat_hal.sensor import sensor
+
+
+class psu(devicebase):
+ __pmbus = None
+ __e2loc = None
+ __productManufacturer = None # : ARTESYN
+ __productName = None # : CRPS550W
+ __productPartModelName = None # : CSU550AP-3-300
+ __productVersion = None # : AB
+ __productSerialNumber = None # : M623UZ00JYABL
+ __AirFlow = None # 'N/A'
+ __AirFlowconifg = None
+ __psu_display_name = None # 'N/A'
+ __psu_display_name_conifg = None
+ __psu_not_present_pwm = None
+ __InputStatus_config = None
+ __OutputStatus_config = None
+ __FanSpeed_config = None
+ __Temperature_config = None
+ __InputStatus = None
+ __OutputStatus = None
+ __FanSpeed = None
+ __Temperature = None
+ __FanSpeedMin = None
+ __FanSpeedMax = None
+ __PsuFanNumber = None
+ __FanSpeedTolerance = None
+ __InputsVoltage_config = None
+ __InputsCurrent_config = None
+ __InputsPower_config = None
+ __OutputsVoltage_config = None
+ __OutputsCurrent_config = None
+ __OutputsPower_config = None
+ __InputsVoltage = {}
+ __InputsCurrent = None
+ __InputsPower = None
+ __OutputsVoltage = None
+ __OutputsCurrent = None
+ __OutputsPower = None
+ __InputsType_config = None
+ __InputsType = None
+ __psu_sn_config = None
+ __psu_hw_config = None
+ __psu_pn_config = None
+ __psu_vendor_config = None
+ __TempStatus_config = None
+ __FanStatus_config = None
+ __TempStatus = None
+ __FanStatus = None
+
+ def __init__(self, conf=None):
+ self.pmbus = conf.get("pmbusloc", None)
+ self.e2loc = conf.get("e2loc", None)
+ self.e2_type = conf.get('e2_type', "fru")
+ self.__presentconfig = conf.get("present", None)
+ self.name = conf.get("name", None)
+ self.get_threshold_by_model = conf.get("get_threshold_by_model", 0)
+ self.AirFlowconifg = conf.get("airflow", None)
+ self.psu_display_name_conifg = conf.get("psu_display_name", None)
+ self.psu_not_present_pwm = conf.get("psu_not_present_pwm", 100)
+ self.Temperature_config = conf.get("Temperature", None)
+ self.Temperature = sensor(self.Temperature_config, self.get_psu_model)
+
+ self.PsuFanNumber = conf.get('psu_fan_number', 1)
+ self.FanSpeedTolerance = conf.get('psu_fan_tolerance', 30)
+ self.FanSpeed_config = conf.get("FanSpeed", None)
+ self.FanSpeed = sensor(self.FanSpeed_config, self.get_psu_model)
+
+ self.__InputsVoltage_config = conf.get("InputsVoltage", None)
+ self.generate_psu_input_vol(self.__InputsVoltage_config)
+ self.__InputsCurrent_config = conf.get("InputsCurrent", None)
+ self.InputsCurrent = sensor(self.__InputsCurrent_config, self.get_psu_model)
+ self.__InputsPower_config = conf.get("InputsPower", None)
+ self.InputsPower = sensor(self.__InputsPower_config, self.get_psu_model)
+ self.__OutputsVoltage_config = conf.get("OutputsVoltage", None)
+ self.OutputsVoltage = sensor(self.__OutputsVoltage_config, self.get_psu_model)
+ self.__OutputsCurrent_config = conf.get("OutputsCurrent", None)
+ self.OutputsCurrent = sensor(self.__OutputsCurrent_config, self.get_psu_model)
+ self.__OutputsPower_config = conf.get("OutputsPower", None)
+ self.OutputsPower = sensor(self.__OutputsPower_config, self.get_psu_model)
+
+ self.__InputStatus_config = conf.get("InputsStatus", None)
+ self.__OutputStatus_config = conf.get("OutputsStatus", None)
+ self.__InputsType_config = conf.get('InputsType', None)
+ self.__psu_sn_config = conf.get('psu_sn', None)
+ self.__psu_hw_config = conf.get('psu_hw', None)
+ self.__psu_pn_config = conf.get('psu_pn', None)
+ self.__psu_vendor_config = conf.get('psu_vendor', None)
+ self.__TempStatus_config = conf.get("TempStatus", None)
+ self.__FanStatus_config = conf.get("FanStatus", None)
+
+ def get_psu_model(self):
+ if self.productPartModelName is None:
+ ret = self.get_fru_info()
+ if ret is False:
+ return None
+ return self.productPartModelName
+
+ def generate_psu_input_vol(self, config):
+ tmp = {}
+ for (key, item) in config.items():
+ tmp.setdefault(key, sensor(item, self.get_psu_model))
+ self.__InputsVoltage = tmp
+
+ def get_psu_sensor_by_name(self, psutype):
+ return self.__InputsVoltage.get(psutype) or self.__InputsVoltage.get('other')
+
+ @property
+ def InputsVoltage(self):
+ psutype = self.InputsType
+ input_sensor = self.get_psu_sensor_by_name(psutype)
+ if input_sensor is None:
+ return None
+ return input_sensor
+
+ @InputsVoltage.setter
+ def InputsVoltage(self, val):
+ self.__InputsVoltage = val
+
+ @property
+ def InputsCurrent(self):
+ return self.__InputsCurrent
+
+ @InputsCurrent.setter
+ def InputsCurrent(self, val):
+ self.__InputsCurrent = val
+
+ @property
+ def InputsPower(self):
+ return self.__InputsPower
+
+ @InputsPower.setter
+ def InputsPower(self, val):
+ self.__InputsPower = val
+
+ @property
+ def OutputsVoltage(self):
+ return self.__OutputsVoltage
+
+ @OutputsVoltage.setter
+ def OutputsVoltage(self, val):
+ self.__OutputsVoltage = val
+
+ @property
+ def OutputsCurrent(self):
+ return self.__OutputsCurrent
+
+ @OutputsCurrent.setter
+ def OutputsCurrent(self, val):
+ self.__OutputsCurrent = val
+
+ @property
+ def OutputsPower(self):
+ return self.__OutputsPower
+
+ @OutputsPower.setter
+ def OutputsPower(self, val):
+ self.__OutputsPower = val
+
+ @property
+ def InputStatus(self):
+ if self.__InputStatus_config is None:
+ return None
+ if self.present is False:
+ self.__InputStatus = False
+ else:
+ ret, val = self.get_value(self.__InputStatus_config)
+ mask = self.__InputStatus_config.get("mask")
+ if ret is True:
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ ttt = value & mask
+ okval = self.__InputStatus_config.get("okval", 0)
+ if ttt == okval:
+ self.__InputStatus = True
+ else:
+ self.__InputStatus = False
+ else:
+ self.__InputStatus = False
+ return self.__InputStatus
+
+ @InputStatus.setter
+ def InputStatus(self, val):
+ self.__InputStatus = val
+
+ @property
+ def TempStatus(self):
+ if self.__TempStatus_config is None:
+ return None
+ if self.present is False:
+ self.__TempStatus = False
+ else:
+ ret, val = self.get_value(self.__TempStatus_config)
+ mask = self.__TempStatus_config.get("mask")
+ if ret is True:
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ ttt = value & mask
+ okval = self.__TempStatus_config.get("okval", 0)
+ if ttt == okval:
+ self.__TempStatus = True
+ else:
+ self.__TempStatus = False
+ else:
+ self.__TempStatus = False
+ return self.__TempStatus
+
+ @TempStatus.setter
+ def TempStatus(self, val):
+ self.__TempStatus = val
+
+ @property
+ def FanStatus(self):
+ if self.__FanStatus_config is None:
+ return None
+ if self.present is False:
+ self.__FanStatus = False
+ else:
+ ret, val = self.get_value(self.__FanStatus_config)
+ mask = self.__FanStatus_config.get("mask")
+ if ret is True:
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ ttt = value & mask
+ okval = self.__FanStatus_config.get("okval", 0)
+ if ttt == okval:
+ self.__FanStatus = True
+ else:
+ self.__FanStatus = False
+ else:
+ self.__FanStatus = False
+ return self.__FanStatus
+
+ @FanStatus.setter
+ def FanStatus(self, val):
+ self.__FanStatus = val
+
+ def get_input_type_pmbus(self):
+ psutypedecode = self.__InputsType_config.get('psutypedecode', {})
+ if self.present is False:
+ self.__InputsType = psutypedecode.get(0x00)
+ else:
+ ret, val = self.get_value(self.__InputsType_config)
+ self.__InputsType = self.__InputsType_config.get(val, None)
+ if self.__InputsType is not None:
+ return self.__InputsType
+ if ret is True and val in psutypedecode:
+ self.__InputsType = psutypedecode.get(val)
+ else:
+ self.__InputsType = psutypedecode.get(0x00)
+ return self.__InputsType
+
+ def get_input_type_fru(self):
+ self.__InputsType = 'N/A'
+ if self.productPartModelName is None:
+ ret = self.get_fru_info()
+ if ret is False:
+ return self.__InputsType
+ psutypedecode = self.__InputsType_config.get('psutypedecode', {})
+ for key, value in psutypedecode.items():
+ if self.productPartModelName in value:
+ self.__InputsType = key
+ return self.__InputsType
+
+ @property
+ def InputsType(self):
+ gettype = self.__InputsType_config.get('gettype', "pmbus")
+ if gettype == "pmbus":
+ return self.get_input_type_pmbus()
+
+ if gettype == "fru":
+ return self.get_input_type_fru()
+
+ self.__InputsType = 'N/A'
+ return self.__InputsType
+
+ @InputsType.setter
+ def InputsType(self, val):
+ self.__InputsType = val
+
+ @property
+ def FanSpeedMin(self):
+ return self.__FanSpeedMin
+
+ @FanSpeedMin.setter
+ def FanSpeedMin(self, val):
+ self.__FanSpeedMin = val
+
+ @property
+ def FanSpeedMax(self):
+ return self.__FanSpeedMax
+
+ @FanSpeedMax.setter
+ def FanSpeedMax(self, val):
+ self.__FanSpeedMax = val
+
+ @property
+ def PsuFanNumber(self):
+ return self.__PsuFanNumber
+
+ @PsuFanNumber.setter
+ def PsuFanNumber(self, val):
+ self.__PsuFanNumber = val
+
+ @property
+ def FanSpeedTolerance(self):
+ return self.__FanSpeedTolerance
+
+ @FanSpeedTolerance.setter
+ def FanSpeedTolerance(self, val):
+ self.__FanSpeedTolerance = val
+
+ @property
+ def OutputStatus(self):
+ if self.__OutputStatus_config is None:
+ return None
+ if self.present is False:
+ self.__OutputStatus = False
+ else:
+ ret, val = self.get_value(self.__OutputStatus_config)
+ mask = self.__OutputStatus_config.get("mask")
+ if ret is True:
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ ttt = value & mask
+ okval = self.__OutputStatus_config.get("okval", 0)
+ if ttt == okval:
+ self.__OutputStatus = True
+ else:
+ self.__OutputStatus = False
+ else:
+ self.__OutputStatus = False
+ return self.__OutputStatus
+
+ @OutputStatus.setter
+ def OutputStatus(self, val):
+ self.__OutputStatus = val
+
+ @property
+ def FanSpeed(self):
+ return self.__FanSpeed
+
+ @FanSpeed.setter
+ def FanSpeed(self, val):
+ self.__FanSpeed = val
+
+ @property
+ def Temperature(self):
+ return self.__Temperature
+
+ @Temperature.setter
+ def Temperature(self, val):
+ self.__Temperature = val
+
+ @property
+ def Temperature_config(self):
+ return self.__Temperature_config
+
+ @Temperature_config.setter
+ def Temperature_config(self, val):
+ self.__Temperature_config = val
+
+ @property
+ def AirFlowconifg(self):
+ return self.__AirFlowconifg
+
+ @AirFlowconifg.setter
+ def AirFlowconifg(self, val):
+ self.__AirFlowconifg = val
+
+ @property
+ def psu_display_name_conifg(self):
+ return self.__psu_display_name_conifg
+
+ @psu_display_name_conifg.setter
+ def psu_display_name_conifg(self, val):
+ self.__psu_display_name_conifg = val
+
+ @property
+ def pmbus(self):
+ return self.__pmbus
+
+ @pmbus.setter
+ def pmbus(self, val):
+ self.__pmbus = val
+
+ @property
+ def e2loc(self):
+ return self.__e2loc
+
+ @e2loc.setter
+ def e2loc(self, val):
+ self.__e2loc = val
+
+ @property
+ def AirFlow(self):
+ return self.__AirFlow
+
+ @AirFlow.setter
+ def AirFlow(self, val):
+ self.__AirFlow = val
+
+ @property
+ def psu_display_name(self):
+ return self.__psu_display_name
+
+ @psu_display_name.setter
+ def psu_display_name(self, val):
+ self.__psu_display_name = val
+
+ @property
+ def psu_not_present_pwm(self):
+ return self.__psu_not_present_pwm
+
+ @psu_not_present_pwm.setter
+ def psu_not_present_pwm(self, val):
+ self.__psu_not_present_pwm = val
+
+ @property
+ def present(self):
+ ret, val = self.get_value(self.__presentconfig)
+ if ret is False or val is None or val == "no_support" or val == "NA":
+ return False
+ mask = self.__presentconfig.get("mask")
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ ttt = value & mask
+ okval = self.__presentconfig.get("okval", 0)
+ if ttt == okval:
+ return True
+ return False
+
+ @property
+ def productManufacturer(self):
+ return self.__productManufacturer
+
+ @productManufacturer.setter
+ def productManufacturer(self, val):
+ self.__productManufacturer = val
+
+ @property
+ def productName(self):
+ return self.__productName
+
+ @productName.setter
+ def productName(self, val):
+ self.__productName = val
+
+ @property
+ def productPartModelName(self):
+ return self.__productPartModelName
+
+ @productPartModelName.setter
+ def productPartModelName(self, val):
+ self.__productPartModelName = val
+
+ @property
+ def productVersion(self):
+ return self.__productVersion
+
+ @productVersion.setter
+ def productVersion(self, val):
+ self.__productVersion = val
+
+ @property
+ def productSerialNumber(self):
+ return self.__productSerialNumber
+
+ @productSerialNumber.setter
+ def productSerialNumber(self, val):
+ self.__productSerialNumber = val
+
+ @property
+ def psu_sn_sysfs(self):
+ if self.__psu_sn_config is None:
+ return None
+ ret, val = self.get_value(self.__psu_sn_config)
+ if ret is False or val is None:
+ return None
+ return val
+
+ @property
+ def psu_hw_sysfs(self):
+ if self.__psu_hw_config is None:
+ return None
+ ret, val = self.get_value(self.__psu_hw_config)
+ if ret is False or val is None:
+ return None
+ return val
+
+ @property
+ def psu_pn_sysfs(self):
+ if self.__psu_pn_config is None:
+ return None
+ ret, val = self.get_value(self.__psu_pn_config)
+ if ret is False or val is None:
+ return None
+ return val
+
+ @property
+ def psu_vendor_sysfs(self):
+ if self.__psu_vendor_config is None:
+ return None
+ ret, val = self.get_value(self.__psu_vendor_config)
+ if ret is False or val is None:
+ return None
+ return val
+
+ def __str__(self):
+ formatstr = \
+ "name : %s \n" \
+ "productManufacturer : %s \n" \
+ "productName : %s \n" \
+ "productPartModelName: %s \n" \
+ "productVersion : %s \n" \
+ "productSerialNumber : %s \n" \
+ "AirFlow : %s \n" \
+
+ tmpstr = formatstr % (self.name, self.productManufacturer,
+ self.productName, self.productPartModelName,
+ self.productVersion, self.productSerialNumber, self.AirFlow)
+ return tmpstr
+
+ def get_fan_speed_pwm(self):
+ if self.pmbus is None:
+ return None
+ if self.present is False:
+ return self.psu_not_present_pwm
+ selfconfig = {}
+ selfconfig['bus'] = self.pmbus['bus']
+ selfconfig['addr'] = self.pmbus['addr']
+ selfconfig['way'] = 'i2cword'
+ selfconfig['offset'] = 0x3b
+ ret, val = self.get_value(selfconfig)
+ if ret is True:
+ return val
+ return None
+
+ def set_fan_speed_pwm(self, pwm):
+ '''
+ pmbus
+ if duty:
+ i2cset -f -y 0x3b 0x0064 wp
+ '''
+ if self.present is False:
+ return None
+
+ if self.pmbus is None:
+ return None
+
+ if 0 <= pwm <= 100:
+ # enable duty first
+ selfconfig = {}
+
+ selfconfig['bus'] = self.pmbus['bus']
+ selfconfig['addr'] = self.pmbus['addr']
+ selfconfig['way'] = 'i2cpec'
+ selfconfig['offset'] = 0x3a
+ self.set_value(selfconfig, 0x80)
+
+ selfconfig['way'] = 'i2cwordpec'
+ selfconfig['offset'] = 0x3b
+ bytetmp = pwm
+ ret, val = self.set_value(selfconfig, int(bytetmp))
+ if ret is True:
+ return True
+ return None
+ raise Exception("pwm not in range [0,100]")
+
+ def get_fru_info_by_sysfs(self):
+ try:
+ psu_sn = self.psu_sn_sysfs
+ psu_hw = self.psu_hw_sysfs
+ psu_pn = self.psu_pn_sysfs
+ psu_vendor = self.psu_vendor_sysfs
+ if psu_sn is None or psu_hw is None or psu_pn is None or psu_vendor is None:
+ return False
+ self.productSerialNumber = psu_sn.strip().replace(chr(0), "")
+ self.productVersion = psu_hw.strip()
+ self.productPartModelName = psu_pn.strip()
+ self.productManufacturer = psu_vendor.strip().replace(chr(0), "")
+ except Exception:
+ self.productSerialNumber = None
+ self.productVersion = None
+ self.productPartModelName = None
+ self.productManufacturer = None
+ return False
+ return True
+
+ def get_fru_info_by_decode(self):
+ try:
+ eeprom = self.get_eeprom_info(self.e2loc)
+ if eeprom is None:
+ raise Exception("%s:value is none" % self.name)
+ fru = ipmifru()
+ if isinstance(eeprom, bytes):
+ eeprom = self.byteTostr(eeprom)
+ fru.decodeBin(eeprom)
+ if fru.productInfoArea is not None:
+ self.productManufacturer = fru.productInfoArea.productManufacturer.strip()
+ self.productName = fru.productInfoArea.productName.strip()
+ self.productPartModelName = fru.productInfoArea.productPartModelName.strip()
+ self.productVersion = fru.productInfoArea.productVersion.strip()
+ self.productSerialNumber = fru.productInfoArea.productSerialNumber.strip().replace(chr(0), "")
+ except Exception:
+ self.productManufacturer = None
+ self.productName = None
+ self.productPartModelName = None
+ self.productVersion = None
+ self.productSerialNumber = None
+ return False
+ return True
+
+ def get_custfru_info_by_decode(self):
+ try:
+ eeprom = self.get_eeprom_info(self.e2loc)
+ if eeprom is None:
+ raise Exception("%s:value is none" % self.name)
+ custfru = CustFru()
+ if isinstance(eeprom, bytes):
+ eeprom = self.byteTostr(eeprom)
+ custfru.decode(eeprom)
+ self.productManufacturer = custfru.manufacturer.strip()
+ self.productName = custfru.product_name.strip()
+ self.productPartModelName = custfru.product_name.strip()
+ self.productVersion = custfru.version.strip()
+ self.productSerialNumber = custfru.serial_number.strip().replace(chr(0), "")
+ except Exception:
+ self.productManufacturer = None
+ self.productName = None
+ self.productPartModelName = None
+ self.productVersion = None
+ self.productSerialNumber = None
+ return False
+ return True
+
+ def get_fru_info(self):
+ try:
+ if self.present is not True:
+ raise Exception("%s: not present" % self.name)
+
+ if self.get_fru_info_by_sysfs() is True:
+ return True
+
+ if self.e2_type == "fru":
+ return self.get_fru_info_by_decode()
+
+ if self.e2_type == "custfru":
+ return self.get_custfru_info_by_decode()
+
+ raise Exception("%s: unsupport e2_type: %s" % (self.name, self.e2_type))
+ except Exception:
+ self.productManufacturer = None
+ self.productName = None
+ self.productPartModelName = None
+ self.productVersion = None
+ self.productSerialNumber = None
+ return False
+
+ def get_AirFlow(self):
+ if self.productPartModelName is None:
+ ret = self.get_fru_info()
+ if ret is False:
+ self.AirFlow = None
+ return False
+ if self.AirFlowconifg is None:
+ self.AirFlow = None
+ return False
+ for i in self.AirFlowconifg:
+ if self.productPartModelName in self.AirFlowconifg[i]:
+ self.AirFlow = i
+ return True
+ self.AirFlow = None
+ return False
+
+ def get_psu_display_name(self):
+ if self.productPartModelName is None:
+ ret = self.get_fru_info()
+ if ret is False:
+ self.psu_display_name = None
+ return False
+ if self.psu_display_name_conifg is None:
+ self.psu_display_name = self.productPartModelName
+ return False
+ for i in self.psu_display_name_conifg:
+ if self.productPartModelName in self.psu_display_name_conifg[i]:
+ self.psu_display_name = i
+ return True
+ self.psu_display_name = self.productPartModelName
+ return False
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/rotor.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/rotor.py
new file mode 100644
index 000000000000..6ac934732cbb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/rotor.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# rotor.py
+# Python implementation of the Class rotor
+#
+#######################################################
+from plat_hal.devicebase import devicebase
+from plat_hal.sensor import sensor
+
+
+class rotor(devicebase):
+ __rotor_Running = None
+ __rotor_HwAlarm_conf = None
+ __rotor_Speed = None
+ __rotor_run_conf = None
+ __Speedconfig = None
+ __i2c_speed = None
+ __SpeedMin = None
+ __SpeedMax = None
+ __SpeedTolerance = None
+
+ def __init__(self, conf=None):
+ self.name = conf.get('name', None)
+ self.rotor_HwAlarm_conf = conf.get('HwAlarm', None)
+ self.rotor_run_conf = conf.get('Running', None)
+ self.SpeedMin = conf.get('SpeedMin', None)
+ self.SpeedMax = conf.get('SpeedMax', None)
+ self.Tolerance = conf.get('tolerance', 30)
+ self.rotor_Speed = sensor(conf.get('Speed', None))
+ self.Speedconfig = conf.get('Set_speed', None)
+
+ def getRunning(self):
+ ret, val = self.get_value(self.rotor_run_conf)
+ if ret is False or val is None or val == "no_support" or val == "NA":
+ return False
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ mask = self.rotor_run_conf.get("mask")
+ is_runing_value = self.rotor_run_conf.get("is_runing")
+ flag = value & mask
+ if flag == is_runing_value:
+ return True
+ return False
+
+ @property
+ def SpeedMin(self):
+ return self.__SpeedMin
+
+ @SpeedMin.setter
+ def SpeedMin(self, val):
+ self.__SpeedMin = val
+
+ @property
+ def SpeedMax(self):
+ return self.__SpeedMax
+
+ @SpeedMax.setter
+ def SpeedMax(self, val):
+ self.__SpeedMax = val
+
+ @property
+ def Tolerance(self):
+ return self.__SpeedTolerance
+
+ @Tolerance.setter
+ def Tolerance(self, val):
+ self.__SpeedTolerance = val
+
+ @property
+ def i2c_speed(self):
+ ret, val = self.get_value(self.Speedconfig)
+ if ret is False:
+ return None
+ if val is not None:
+ self.__i2c_speed = val
+ return self.__i2c_speed
+
+ def feed_watchdog(self):
+ ret, val = self.get_value(self.Speedconfig)
+ if ret is False:
+ return False, None
+ if val is not None:
+ ret, val = self.set_value(self.Speedconfig, val)
+ return ret, val
+ return False, None
+
+ @i2c_speed.setter
+ def i2c_speed(self, val):
+ self.__i2c_speed = val
+
+ @property
+ def Speedconfig(self):
+ return self.__Speedconfig
+
+ @Speedconfig.setter
+ def Speedconfig(self, val):
+ self.__Speedconfig = val
+
+ @property
+ def rotor_run_conf(self):
+ return self.__rotor_run_conf
+
+ @rotor_run_conf.setter
+ def rotor_run_conf(self, val):
+ self.__rotor_run_conf = val
+
+ @property
+ def rotor_Speed(self):
+ return self.__rotor_Speed
+
+ @rotor_Speed.setter
+ def rotor_Speed(self, val):
+ self.__rotor_Speed = val
+
+ @property
+ def rotor_HwAlarm(self):
+ ret, val = self.get_value(self.rotor_HwAlarm_conf)
+ mask = self.rotor_HwAlarm_conf.get("mask")
+ no_alarm_value = self.rotor_HwAlarm_conf.get("no_alarm")
+ if ret is False or val is None or val == "NA":
+ return False
+ if isinstance(val, str):
+ value = int(val, 16)
+ else:
+ value = val
+ flag = value & mask
+ if flag == no_alarm_value:
+ return False
+ return True
+
+ @property
+ def rotor_HwAlarm_conf(self):
+ return self.__rotor_HwAlarm_conf
+
+ @rotor_HwAlarm_conf.setter
+ def rotor_HwAlarm_conf(self, val):
+ self.__rotor_HwAlarm_conf = val
+
+ @property
+ def rotor_Running(self):
+ self.__rotor_Running = self.getRunning()
+ return self.__rotor_Running
+
+ @rotor_Running.setter
+ def rotor_Running(self, val):
+ self.__rotor_Running = val
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/sensor.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/sensor.py
new file mode 100644
index 000000000000..af2a5384b618
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/sensor.py
@@ -0,0 +1,274 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# sensor.py
+# Python implementation of the Class sensor
+#
+#######################################################
+import time
+from plat_hal.devicebase import devicebase
+
+
+class sensor(devicebase):
+
+ __Value = None
+ __Min = None
+ __Max = None
+ __Low = None
+ __High = None
+ __ValueConfig = None
+ __Flag = None
+ __Unit = None
+ __format = None
+ __read_times = None
+
+ __Min_config = None
+ __Max_config = None
+ __Low_config = None
+ __High_config = None
+
+ @property
+ def Min_config(self):
+ return self.__Min_config
+
+ @Min_config.setter
+ def Min_config(self, val):
+ self.__Min_config = val
+
+ @property
+ def Max_config(self):
+ return self.__Max_config
+
+ @Max_config.setter
+ def Max_config(self, val):
+ self.__Max_config = val
+
+ @property
+ def Low_config(self):
+ return self.__Low_config
+
+ @Low_config.setter
+ def Low_config(self, val):
+ self.__Low_config = val
+
+ @property
+ def High_config(self):
+ return self.__High_config
+
+ @High_config.setter
+ def High_config(self, val):
+ self.__High_config = val
+
+ @property
+ def Unit(self):
+ return self.__Unit
+
+ @Unit.setter
+ def Unit(self, val):
+ self.__Unit = val
+
+ @property
+ def format(self):
+ return self.__format
+
+ @format.setter
+ def format(self, val):
+ self.__format = val
+
+ @property
+ def read_times(self):
+ return self.__read_times
+
+ @read_times.setter
+ def read_times(self, val):
+ self.__read_times = val
+
+ @property
+ def ValueConfig(self):
+ return self.__ValueConfig
+
+ @ValueConfig.setter
+ def ValueConfig(self, val):
+ self.__ValueConfig = val
+
+ @property
+ def Flag(self):
+ return self.__Flag
+
+ @Flag.setter
+ def Flag(self, val):
+ self.__Flag = val
+
+ def get_median(self, value_config, read_times):
+ val_list = []
+ for i in range(0, read_times):
+ ret, real_value = self.get_value(value_config)
+ if i != (read_times - 1):
+ time.sleep(0.01)
+ if ret is False or real_value is None:
+ continue
+ val_list.append(real_value)
+ val_list.sort()
+ if val_list:
+ return True, val_list[int((len(val_list) - 1) / 2)]
+ return False, None
+
+ @property
+ def Value(self):
+ try:
+ ret, val = self.get_median(self.ValueConfig, self.read_times)
+ if ret is False or val is None:
+ return None
+ if self.format is None:
+ self.__Value = int(val)
+ else:
+ self.__Value = self.get_format_value(self.format % val)
+ self.__Value = round(float(self.__Value), 3)
+ except Exception:
+ return None
+ return self.__Value
+
+ @Value.setter
+ def Value(self, val):
+ self.__Value = val
+
+ @property
+ def Min(self):
+ try:
+ if isinstance(self.Min_config, dict):
+ if self.call_back is None:
+ self.__Min = self.Min_config.get("other")
+ else:
+ ret = self.call_back()
+ if ret not in self.Min_config:
+ self.__Min = self.Min_config.get("other")
+ else:
+ self.__Min = self.Min_config[ret]
+ else:
+ self.__Min = self.Min_config
+
+ if self.__Min is None:
+ return None
+
+ if self.format is not None:
+ self.__Min = self.get_format_value(self.format % self.__Min)
+ self.__Min = round(float(self.__Min), 3)
+ except Exception:
+ return None
+ return self.__Min
+
+ @Min.setter
+ def Min(self, val):
+ self.__Min = val
+
+ @property
+ def Max(self):
+ try:
+ if isinstance(self.Max_config, dict):
+ if self.call_back is None:
+ self.__Max = self.Max_config.get("other")
+ else:
+ ret = self.call_back()
+ if ret not in self.Max_config:
+ self.__Max = self.Max_config.get("other")
+ else:
+ self.__Max = self.Max_config[ret]
+ else:
+ self.__Max = self.Max_config
+
+ if self.__Max is None:
+ return None
+
+ if self.format is not None:
+ self.__Max = self.get_format_value(self.format % self.__Max)
+ self.__Max = round(float(self.__Max), 3)
+ except Exception:
+ return None
+ return self.__Max
+
+ @Max.setter
+ def Max(self, val):
+ self.__Max = val
+
+ @property
+ def Low(self):
+ try:
+ if isinstance(self.Low_config, dict):
+ if self.call_back is None:
+ self.__Low = self.Low_config.get("other")
+ else:
+ ret = self.call_back()
+ if ret not in self.Low_config:
+ self.__Low = self.Low_config.get("other")
+ else:
+ self.__Low = self.Low_config[ret]
+ else:
+ self.__Low = self.Low_config
+
+ if self.__Low is None:
+ return None
+
+ if self.format is not None:
+ self.__Low = self.get_format_value(self.format % self.__Low)
+ self.__Low = round(float(self.__Low), 3)
+ except Exception:
+ return None
+ return self.__Low
+
+ @Low.setter
+ def Low(self, val):
+ self.__Low = val
+
+ @property
+ def High(self):
+ try:
+ if isinstance(self.High_config, dict):
+ if self.call_back is None:
+ self.__High = self.High_config.get("other")
+ else:
+ ret = self.call_back()
+ if ret not in self.High_config:
+ self.__High = self.High_config.get("other")
+ else:
+ self.__High = self.High_config[ret]
+ else:
+ self.__High = self.High_config
+
+ if self.__High is None:
+ return None
+
+ if self.format is not None:
+ self.__High = self.get_format_value(self.format % self.__High)
+ self.__High = round(float(self.__High), 3)
+ except Exception:
+ return None
+ return self.__High
+
+ @High.setter
+ def High(self, val):
+ self.__High = val
+
+ def __init__(self, conf=None, call_back=None):
+ self.ValueConfig = conf.get("value", None)
+ self.Flag = conf.get("flag", None)
+ self.Min_config = conf.get("Min", None)
+ self.Max_config = conf.get("Max", None)
+ self.Low_config = conf.get("Low", None)
+ self.High_config = conf.get("High", None)
+ self.Unit = conf.get('Unit', None)
+ self.format = conf.get('format', None)
+ self.read_times = conf.get('read_times', 1)
+ self.call_back = call_back
+
+ def __str__(self):
+ formatstr = \
+ "ValueConfig: : %s \n" \
+ "Min : %s \n" \
+ "Max : %s \n" \
+ "Unit : %s \n" \
+ "format: : %s \n"
+
+ tmpstr = formatstr % (self.ValueConfig, self.Min,
+ self.Max, self.Unit,
+ self.format)
+ return tmpstr
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/temp.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/temp.py
new file mode 100644
index 000000000000..a202c20339c9
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/plat_hal/temp.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+#######################################################
+#
+# temp.py
+# Python implementation of the Class temp
+#
+#######################################################
+import os
+import syslog
+from plat_hal.sensor import sensor
+
+
+PLATFORM_HAL_TEMP_DEBUG_FILE = "/etc/.platform_hal_temp_debug_flag"
+
+
+def platform_hal_temp_debug(s):
+ if os.path.exists(PLATFORM_HAL_TEMP_DEBUG_FILE):
+ syslog.openlog("PLATFORM_HAL_TEPM", syslog.LOG_PID)
+ syslog.syslog(syslog.LOG_DEBUG, s)
+
+
+class temp(sensor):
+ def __init__(self, conf=None):
+ super(temp, self).__init__(conf.get('Temperature', None))
+ self.name = conf.get("name", None)
+ self.temp_id = conf.get("temp_id", None)
+ self.api_name = conf.get("api_name", self.name)
+ self.fix_value = conf.get("fix_value", None)
+ self.temp_invalid = conf.get("invalid", None)
+ self.temp_error = conf.get("error", None)
+
+ def temp_cali_by_fan_pwm(self, param, origin_value):
+ fan_pwm_conf = param.get("fan_pwm")
+ temp_fix_list = param.get("temp_fix_list")
+
+ ret, val = self.get_value(fan_pwm_conf)
+ if ret is False or val is None:
+ platform_hal_temp_debug("temp calibration get fan pwm failed, msg: %s, return None" % (val))
+ return None
+
+ fan_pwm = int(val)
+ for item in temp_fix_list:
+ if item["min"] <= fan_pwm <= item["max"]:
+ fix_value = origin_value + item["fix"]
+ platform_hal_temp_debug("temp calibration by fan pwm, origin_value: %s, pwm: %s, fix_value: %s" %
+ (origin_value, fan_pwm, fix_value))
+ return fix_value
+ platform_hal_temp_debug("temp calibration by fan pwm, origin_value: %s, pwm: %s, not match return None" %
+ (origin_value, fan_pwm))
+ return None
+
+ def fix_temp_value(self, origin_value):
+ try:
+ fix_type = self.fix_value.get("fix_type")
+
+ if fix_type == "func":
+ func_name = self.fix_value.get("func_name")
+ func_param = self.fix_value.get("func_param")
+ func = getattr(self, func_name)
+ if func is None:
+ platform_hal_temp_debug("function %s, not defined" % func_name)
+ return None
+ value = func(func_param, origin_value)
+ return value
+
+ if fix_type == "config":
+ coefficient = self.fix_value.get("coefficient", 1)
+ addend = self.fix_value.get("addend", 0)
+ value = (origin_value + addend) * coefficient
+ platform_hal_temp_debug("temp calibration by config, coefficient: %s, addend: %s, origin_value: %s, fix_value: %s" %
+ (coefficient, addend, origin_value, value))
+ return value
+
+ platform_hal_temp_debug("unsupport fix type: %s, return origin value: %s" % (fix_type, origin_value))
+ return origin_value
+ except Exception as e:
+ platform_hal_temp_debug("fix_temp_value raise exception, msg: %s" % (str(e)))
+ return None
+
+ def get_max_value(self, conf):
+ try:
+ ret, val = self.get_value(conf)
+ if ret is False or val is None:
+ return None
+ return val
+ except Exception:
+ return None
+
+ def check_flag(self):
+ try:
+ okbit = self.Flag.get('okbit')
+ okval = self.Flag.get('okval')
+ ret, val = self.get_value(self.Flag)
+ if (ret is False) or (val is None):
+ return False
+ val_t = (int(val) & (1 << okbit)) >> okbit
+ if val_t != okval:
+ return False
+ except Exception:
+ return False
+ return True
+
+ @property
+ def Value(self):
+ try:
+ if self.Flag is not None:
+ if self.check_flag() is False:
+ return None
+ if isinstance(self.ValueConfig, list):
+ max_val = None
+ for i in self.ValueConfig:
+ tmp = self.get_max_value(i)
+ if tmp is None:
+ continue
+ if max_val is None or max_val < tmp:
+ max_val = tmp
+ if max_val is None:
+ return None
+ if self.format is None:
+ self.__Value = int(max_val)
+ else:
+ self.__Value = self.get_format_value(self.format % max_val)
+ else:
+ ret, val = self.get_value(self.ValueConfig)
+ if ret is False or val is None:
+ return None
+ if self.format is None:
+ self.__Value = int(val)
+ else:
+ self.__Value = self.get_format_value(self.format % val)
+ except Exception:
+ return None
+ if self.fix_value is not None and self.__Value != self.temp_invalid and self.__Value != self.temp_error:
+ self.__Value = self.fix_temp_value(self.__Value)
+ return self.__Value
+
+ @Value.setter
+ def Value(self, val):
+ self.__Value = val
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/restful_util/__init__.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/restful_util/__init__.py
new file mode 100755
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/restful_util/restful_api.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/restful_util/restful_api.py
new file mode 100755
index 000000000000..2cb7f5273a44
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/restful_util/restful_api.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+import os
+import syslog
+
+import requests
+
+class RestfulApiClient():
+ Debug_file = "/tmp/restful_api_debug"
+ BmcBaseUrl = 'http://240.1.1.2:8080'
+ NetworkUrl = '/api/v1.0/network'
+ PowerUrl = '/api/v1.0/power'
+ HostnameUrl = '/api/v1.0/hostname'
+ EventsUrl = '/api/v1.0/events'
+ SensorsUrl = '/api/v1.0/sys_switch/sensors'
+ SyseepromUrl = '/api/v1.0/syseeprom'
+ FansUrl = '/api/v1.0/sys_switch/fans'
+ # FanUrl = '/api/v1.0/sys_switch/fan/fan1'
+ FanUrl = '/api/v1.0/sys_switch/fan/'
+ PsusUrl = '/api/v1.0/sys_switch/psus'
+ # PsuUrl = '/api/v1.0/sys_switch/psu/psu1'
+ PsuUrl = '/api/v1.0/sys_switch/psu/'
+ LEDsUrl = '/api/v1.0/sys_switch/leds'
+ FirmwaresUrl = '/api/v1.0/sys_switch/firmwares'
+ WatchdogsUrl = '/api/v1.0/watchdog-lambda-os'
+ UsersUrl = '/api/v1.0/users'
+ TimeUrl = '/api/v1.0/time'
+ TimezoneUrl = '/api/v1.0/timezone'
+ NtpUrl = '/api/v1.0/ntp'
+ PowerUrl = '/api/v1.0/power'
+
+ def restful_api_error_log(self, msg):
+ syslog.openlog("restful_api")
+ syslog.syslog(syslog.LOG_ERR, msg)
+ syslog.closelog()
+
+ def restful_api_debug_log(self, msg):
+ if os.path.exists(self.Debug_file):
+ syslog.openlog("restful_api")
+ syslog.syslog(syslog.LOG_DEBUG, msg)
+ syslog.closelog()
+
+ def get_request(self, url, time_out=(30, 30)):
+ try:
+ full_url = self.BmcBaseUrl + url
+ self.restful_api_debug_log("GET: %s" % full_url)
+ response = requests.get(full_url, timeout=time_out)
+ self.restful_api_debug_log("RET: %s" % str(response.json()))
+ return response.json()
+ except Exception as e:
+ self.restful_api_error_log(str(e))
+ return None
+
+ def post_request(self, url, data, time_out=(30, 30)):
+ try:
+ full_url = self.BmcBaseUrl + url
+ self.restful_api_debug_log("POST: %s -d %s" % (full_url, str(data)))
+ response = requests.post(full_url, json=data, timeout=time_out)
+ if response.status_code == 200:
+ self.restful_api_debug_log("RET: %s" % str(response.json()))
+ return response.json()
+ else:
+ self.restful_api_error_log("Post request failed. Status code {}".format(response.status_code))
+ return None
+ except Exception as e:
+ self.restful_api_error_log(str(e))
+ return None
+'''
+if __name__ == '__main__':
+ client = RestfulApiClient()
+
+ time_data = client.get_request(client.TimeUrl)
+ print("Current time:", time_data)
+
+ fans = client.get_request(client.FansUrl)
+ print("Current fans:", fans)
+
+ new_time = "2023-08-31 14:41:28 +0800"
+ response = client.post_request(client.TimeUrl, {"time": new_time})
+ print("Time set successfully:", response)
+
+ cmd = "bmc reset cold"
+ response = client.post_request(client.PowerUrl, {"cmd": cmd})
+ print("Time set successfully:", response)
+
+ #sensors = client.get_request(client.SensorsUrl)
+ #print("sensors:", sensors)
+'''
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/__init__.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/baseutil.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/baseutil.py
new file mode 100644
index 000000000000..340a1f7a733f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/baseutil.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+import os
+
+
+def get_machine_info():
+ if not os.path.isfile('/host/machine.conf'):
+ return None
+ machine_vars = {}
+ with open('/host/machine.conf') as machine_file:
+ for line in machine_file:
+ tokens = line.split('=')
+ if len(tokens) < 2:
+ continue
+ machine_vars[tokens[0]] = tokens[1].strip()
+ return machine_vars
+
+
+def get_platform_info(machine_info):
+ if machine_info is not None:
+ if 'onie_platform' in machine_info:
+ return machine_info['onie_platform']
+ if 'aboot_platform' in machine_info:
+ return machine_info['aboot_platform']
+ return None
+
+
+def get_board_id(machine_info):
+ if machine_info is not None:
+ if 'onie_board_id' in machine_info:
+ return machine_info['onie_board_id'].lower()
+ return "NA"
+
+
+def get_onie_machine(machine_info):
+ if machine_info is not None:
+ if 'onie_machine' in machine_info:
+ return machine_info['onie_machine']
+ return None
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/smbus.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/smbus.py
new file mode 100644
index 000000000000..5f1659b3bbf0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/smbus.py
@@ -0,0 +1,772 @@
+#!/usr/bin/env python3
+# smbus2 - A drop-in replacement for smbus-cffi/smbus-python
+# The MIT License (MIT)
+# Copyright (c) 2017 Karl-Petter Lindegaard
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import os
+import sys
+from fcntl import ioctl
+from ctypes import c_uint32, c_uint8, c_uint16, c_char, POINTER, Structure, Array, Union, create_string_buffer, string_at
+
+
+# Commands from uapi/linux/i2c-dev.h
+I2C_SLAVE = 0x0703 # Use this slave address
+I2C_SLAVE_FORCE = 0x0706 # Use this slave address, even if it is already in use by a driver!
+I2C_FUNCS = 0x0705 # Get the adapter functionality mask
+I2C_RDWR = 0x0707 # Combined R/W transfer (one STOP only)
+I2C_SMBUS = 0x0720 # SMBus transfer. Takes pointer to i2c_smbus_ioctl_data
+I2C_PEC = 0x0708
+
+# SMBus transfer read or write markers from uapi/linux/i2c.h
+I2C_SMBUS_WRITE = 0
+I2C_SMBUS_READ = 1
+
+# Size identifiers uapi/linux/i2c.h
+I2C_SMBUS_QUICK = 0
+I2C_SMBUS_BYTE = 1
+I2C_SMBUS_BYTE_DATA = 2
+I2C_SMBUS_WORD_DATA = 3
+I2C_SMBUS_PROC_CALL = 4
+# This isn't supported by Pure-I2C drivers with SMBUS emulation, like those in RaspberryPi, OrangePi, etc :(
+I2C_SMBUS_BLOCK_DATA = 5
+I2C_SMBUS_BLOCK_PROC_CALL = 7 # Like I2C_SMBUS_BLOCK_DATA, it isn't supported by Pure-I2C drivers either.
+I2C_SMBUS_I2C_BLOCK_DATA = 8
+I2C_SMBUS_BLOCK_MAX = 32
+
+# To determine what functionality is present (uapi/linux/i2c.h)
+try:
+ from enum import IntFlag
+except ImportError:
+ IntFlag = int
+
+
+class I2cFunc(IntFlag):
+ """
+ These flags identify the operations supported by an I2C/SMBus device.
+
+ You can test these flags on your `smbus.funcs`
+
+ On newer python versions, I2cFunc is an IntFlag enum, but it
+ falls back to class with a bunch of int constants on older releases.
+ """
+ I2C = 0x00000001
+ ADDR_10BIT = 0x00000002
+ PROTOCOL_MANGLING = 0x00000004 # I2C_M_IGNORE_NAK etc.
+ SMBUS_PEC = 0x00000008
+ NOSTART = 0x00000010 # I2C_M_NOSTART
+ SLAVE = 0x00000020
+ SMBUS_BLOCK_PROC_CALL = 0x00008000 # SMBus 2.0
+ SMBUS_QUICK = 0x00010000
+ SMBUS_READ_BYTE = 0x00020000
+ SMBUS_WRITE_BYTE = 0x00040000
+ SMBUS_READ_BYTE_DATA = 0x00080000
+ SMBUS_WRITE_BYTE_DATA = 0x00100000
+ SMBUS_READ_WORD_DATA = 0x00200000
+ SMBUS_WRITE_WORD_DATA = 0x00400000
+ SMBUS_PROC_CALL = 0x00800000
+ SMBUS_READ_BLOCK_DATA = 0x01000000
+ SMBUS_WRITE_BLOCK_DATA = 0x02000000
+ SMBUS_READ_I2C_BLOCK = 0x04000000 # I2C-like block xfer
+ SMBUS_WRITE_I2C_BLOCK = 0x08000000 # w/ 1-byte reg. addr.
+ SMBUS_HOST_NOTIFY = 0x10000000
+
+ SMBUS_BYTE = 0x00060000
+ SMBUS_BYTE_DATA = 0x00180000
+ SMBUS_WORD_DATA = 0x00600000
+ SMBUS_BLOCK_DATA = 0x03000000
+ SMBUS_I2C_BLOCK = 0x0c000000
+ SMBUS_EMUL = 0x0eff0008
+
+
+# i2c_msg flags from uapi/linux/i2c.h
+I2C_M_RD = 0x0001
+
+# Pointer definitions
+LP_c_uint8 = POINTER(c_uint8)
+LP_c_uint16 = POINTER(c_uint16)
+LP_c_uint32 = POINTER(c_uint32)
+
+
+#############################################################
+# Type definitions as in i2c.h
+
+
+class i2c_smbus_data(Array):
+ """
+ Adaptation of the i2c_smbus_data union in ``i2c.h``.
+
+ Data for SMBus messages.
+ """
+ _length_ = I2C_SMBUS_BLOCK_MAX + 2
+ _type_ = c_uint8
+
+
+class union_i2c_smbus_data(Union):
+ _fields_ = [
+ ("byte", c_uint8),
+ ("word", c_uint16),
+ ("block", i2c_smbus_data)
+ ]
+
+
+union_pointer_type = POINTER(union_i2c_smbus_data)
+
+
+class i2c_smbus_ioctl_data(Structure):
+ """
+ As defined in ``i2c-dev.h``.
+ """
+ _fields_ = [
+ ('read_write', c_uint8),
+ ('command', c_uint8),
+ ('size', c_uint32),
+ ('data', union_pointer_type)]
+ __slots__ = [name for name, type in _fields_]
+
+ @staticmethod
+ def create(read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE_DATA):
+ u = union_i2c_smbus_data()
+ return i2c_smbus_ioctl_data(
+ read_write=read_write, command=command, size=size,
+ data=union_pointer_type(u))
+
+
+#############################################################
+# Type definitions for i2c_rdwr combined transactions
+
+
+class i2c_msg(Structure):
+ """
+ As defined in ``i2c.h``.
+ """
+ _fields_ = [
+ ('addr', c_uint16),
+ ('flags', c_uint16),
+ ('len', c_uint16),
+ ('buf', POINTER(c_char))]
+
+ def __iter__(self):
+ """ Iterator / Generator
+
+ :return: iterates over :py:attr:`buf`
+ :rtype: :py:class:`generator` which returns int values
+ """
+ idx = 0
+ while idx < self.len:
+ yield ord(self.buf[idx])
+ idx += 1
+
+ def __len__(self):
+ return self.len
+
+ def __bytes__(self):
+ return string_at(self.buf, self.len)
+
+ def __repr__(self):
+ return 'i2c_msg(%d,%d,%r)' % (self.addr, self.flags, self.__bytes__())
+
+ def __str__(self):
+ s = self.__bytes__()
+ if sys.version_info.major >= 3:
+ s = ''.join(map(chr, s))
+ return s
+
+ @staticmethod
+ def read(address, length):
+ """
+ Prepares an i2c read transaction.
+
+ :param address: Slave address.
+ :type: address: int
+ :param length: Number of bytes to read.
+ :type: length: int
+ :return: New :py:class:`i2c_msg` instance for read operation.
+ :rtype: :py:class:`i2c_msg`
+ """
+ arr = create_string_buffer(length)
+ return i2c_msg(
+ addr=address, flags=I2C_M_RD, len=length,
+ buf=arr)
+
+ @staticmethod
+ def write(address, buf):
+ """
+ Prepares an i2c write transaction.
+
+ :param address: Slave address.
+ :type address: int
+ :param buf: Bytes to write. Either list of values or str.
+ :type buf: list
+ :return: New :py:class:`i2c_msg` instance for write operation.
+ :rtype: :py:class:`i2c_msg`
+ """
+ if sys.version_info.major >= 3:
+ if isinstance(buf, str):
+ buf = bytes(map(ord, buf))
+ else:
+ buf = bytes(buf)
+ else:
+ if not isinstance(buf, str):
+ buf = ''.join([chr(x) for x in buf])
+ arr = create_string_buffer(buf, len(buf))
+ return i2c_msg(
+ addr=address, flags=0, len=len(arr),
+ buf=arr)
+
+
+class i2c_rdwr_ioctl_data(Structure):
+ """
+ As defined in ``i2c-dev.h``.
+ """
+ _fields_ = [
+ ('msgs', POINTER(i2c_msg)),
+ ('nmsgs', c_uint32)
+ ]
+ __slots__ = [name for name, type in _fields_]
+
+ @staticmethod
+ def create(*i2c_msg_instances):
+ """
+ Factory method for creating a i2c_rdwr_ioctl_data struct that can
+ be called with ``ioctl(fd, I2C_RDWR, data)``.
+
+ :param i2c_msg_instances: Up to 42 i2c_msg instances
+ :rtype: i2c_rdwr_ioctl_data
+ """
+ n_msg = len(i2c_msg_instances)
+ msg_array = (i2c_msg * n_msg)(*i2c_msg_instances)
+ return i2c_rdwr_ioctl_data(
+ msgs=msg_array,
+ nmsgs=n_msg
+ )
+
+
+#############################################################
+
+
+class SMBus(object):
+
+ def __init__(self, bus=None, force=False):
+ """
+ Initialize and (optionally) open an i2c bus connection.
+
+ :param bus: i2c bus number (e.g. 0 or 1)
+ or an absolute file path (e.g. `/dev/i2c-42`).
+ If not given, a subsequent call to ``open()`` is required.
+ :type bus: int or str
+ :param force: force using the slave address even when driver is
+ already using it.
+ :type force: boolean
+ """
+ self.fd = None
+ self.funcs = I2cFunc(0)
+ if bus is not None:
+ self.open(bus)
+ self.address = None
+ self.force = force
+ self._force_last = None
+
+ def __enter__(self):
+ """Enter handler."""
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ """Exit handler."""
+ self.close()
+
+ def open(self, bus):
+ """
+ Open a given i2c bus.
+
+ :param bus: i2c bus number (e.g. 0 or 1)
+ or an absolute file path (e.g. '/dev/i2c-42').
+ :type bus: int or str
+ :raise TypeError: if type(bus) is not in (int, str)
+ """
+ if isinstance(bus, int):
+ filepath = "/dev/i2c-{}".format(bus)
+ elif isinstance(bus, str):
+ filepath = bus
+ else:
+ raise TypeError("Unexpected type(bus)={}".format(type(bus)))
+
+ self.fd = os.open(filepath, os.O_RDWR)
+ self.funcs = self._get_funcs()
+
+ def close(self):
+ """
+ Close the i2c connection.
+ """
+ if self.fd:
+ os.close(self.fd)
+ self.fd = None
+
+ def _set_address(self, address, force=None):
+ """
+ Set i2c slave address to use for subsequent calls.
+
+ :param address:
+ :type address: int
+ :param force:
+ :type force: Boolean
+ """
+ force = force if force is not None else self.force
+ if self.address != address or self._force_last != force:
+ if force is True:
+ ioctl(self.fd, I2C_SLAVE_FORCE, address)
+ else:
+ ioctl(self.fd, I2C_SLAVE, address)
+ self.address = address
+ self._force_last = force
+
+ def _get_funcs(self):
+ """
+ Returns a 32-bit value stating supported I2C functions.
+
+ :rtype: int
+ """
+ f = c_uint32()
+ ioctl(self.fd, I2C_FUNCS, f)
+ return f.value
+
+ def write_quick(self, i2c_addr, force=None):
+ """
+ Perform quick transaction. Throws IOError if unsuccessful.
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param force:
+ :type force: Boolean
+ """
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=0, size=I2C_SMBUS_QUICK)
+ ioctl(self.fd, I2C_SMBUS, msg)
+
+ def read_byte(self, i2c_addr, force=None):
+ """
+ Read a single byte from a device.
+
+ :rtype: int
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param force:
+ :type force: Boolean
+ :return: Read byte value
+ """
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_READ, command=0, size=I2C_SMBUS_BYTE
+ )
+ ioctl(self.fd, I2C_SMBUS, msg)
+ return msg.data.contents.byte
+
+ def write_byte(self, i2c_addr, value, force=None):
+ """
+ Write a single byte to a device.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param value: value to write
+ :type value: int
+ :param force:
+ :type force: Boolean
+ """
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=value, size=I2C_SMBUS_BYTE
+ )
+ ioctl(self.fd, I2C_SMBUS, msg)
+
+ def read_byte_data(self, i2c_addr, register, force=None):
+ """
+ Read a single byte from a designated register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to read
+ :type register: int
+ :param force:
+ :type force: Boolean
+ :return: Read byte value
+ :rtype: int
+ """
+ val_t = -1
+ returnmsg = ""
+ try:
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BYTE_DATA
+ )
+ val_t = ioctl(self.fd, I2C_SMBUS, msg)
+ except Exception as e:
+ self.close()
+ returnmsg = str(e)
+ if val_t < 0:
+ return False, returnmsg
+ return True, msg.data.contents.byte
+
+ def write_byte_data(self, i2c_addr, register, value, force=None):
+ """
+ Write a byte to a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to write to
+ :type register: int
+ :param value: Byte value to transmit
+ :type value: int
+ :param force:
+ :type force: Boolean
+ :rtype: None
+ """
+ val_t = -1
+ returnmsg = ""
+ try:
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA
+ )
+ msg.data.contents.byte = value
+ val_t = ioctl(self.fd, I2C_SMBUS, msg)
+ except Exception as e:
+ returnmsg = str(e)
+ self.close()
+ if val_t < 0:
+ return False, returnmsg or ""
+ return True, ""
+
+ def write_byte_data_pec(self, i2c_addr, register, value, force=None):
+ """
+ Write a byte to a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to write to
+ :type register: int
+ :param value: Byte value to transmit
+ :type value: int
+ :param force:
+ :type force: Boolean
+ :rtype: None
+ """
+ val_t = -1
+ returnmsg = ""
+ try:
+ val_t = ioctl(self.fd, I2C_PEC, 1)
+ if val_t < 0:
+ raise Exception("set pec mod error")
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BYTE_DATA
+ )
+ msg.data.contents.byte = value
+ val_t = ioctl(self.fd, I2C_SMBUS, msg)
+ except Exception as e:
+ returnmsg = str(e)
+ self.close()
+ if val_t < 0:
+ return False, returnmsg or ""
+ return True, ""
+
+ def read_word_data(self, i2c_addr, register, force=None):
+ """
+ Read a single word (2 bytes) from a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to read
+ :type register: int
+ :param force:
+ :type force: Boolean
+ :return: 2-byte word
+ :rtype: int
+ """
+ val_t = -1
+ returnmsg = ""
+ try:
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_WORD_DATA
+ )
+ val_t = ioctl(self.fd, I2C_SMBUS, msg)
+ except Exception as e:
+ returnmsg = str(e)
+ self.close()
+ if val_t < 0:
+ return False, returnmsg or ""
+ return True, msg.data.contents.word
+
+ def write_word_data_pec(self, i2c_addr, register, value, force=None):
+ """
+ Write a byte to a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to write to
+ :type register: int
+ :param value: Word value to transmit
+ :type value: int
+ :param force:
+ :type force: Boolean
+ :rtype: None
+ """
+ val_t = -1
+ returnmsg = ""
+ try:
+ val_t = ioctl(self.fd, I2C_PEC, 1)
+ if val_t < 0:
+ raise Exception("set pec mod error")
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA
+ )
+ msg.data.contents.word = value
+ val_t = ioctl(self.fd, I2C_SMBUS, msg)
+ except Exception as e:
+ returnmsg = str(e)
+ self.close()
+ if val_t < 0:
+ return False, returnmsg or ""
+ return True, ""
+
+ def write_word_data(self, i2c_addr, register, value, force=None):
+ """
+ Write a byte to a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to write to
+ :type register: int
+ :param value: Word value to transmit
+ :type value: int
+ :param force:
+ :type force: Boolean
+ :rtype: None
+ """
+ val_t = -1
+ returnmsg = ""
+ try:
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_WORD_DATA
+ )
+ msg.data.contents.word = value
+ val_t = ioctl(self.fd, I2C_SMBUS, msg)
+ except Exception as e:
+ returnmsg = str(e)
+ self.close()
+ if val_t < 0:
+ return False, returnmsg or ""
+ return True, ""
+
+ def process_call(self, i2c_addr, register, value, force=None):
+ """
+ Executes a SMBus Process Call, sending a 16-bit value and receiving a 16-bit response
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to read/write to
+ :type register: int
+ :param value: Word value to transmit
+ :type value: int
+ :param force:
+ :type force: Boolean
+ :rtype: int
+ """
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_PROC_CALL
+ )
+ msg.data.contents.word = value
+ ioctl(self.fd, I2C_SMBUS, msg)
+ return msg.data.contents.word
+
+ def read_block_data(self, i2c_addr, register, force=None):
+ """
+ Read a block of up to 32-bytes from a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Start register
+ :type register: int
+ :param force:
+ :type force: Boolean
+ :return: List of bytes
+ :rtype: list
+ """
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_BLOCK_DATA
+ )
+ ioctl(self.fd, I2C_SMBUS, msg)
+ length = msg.data.contents.block[0]
+ return msg.data.contents.block[1:length + 1]
+
+ def write_block_data(self, i2c_addr, register, data, force=None):
+ """
+ Write a block of byte data to a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Start register
+ :type register: int
+ :param data: List of bytes
+ :type data: list
+ :param force:
+ :type force: Boolean
+ :rtype: None
+ """
+ length = len(data)
+ if length > I2C_SMBUS_BLOCK_MAX:
+ raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX)
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_DATA
+ )
+ msg.data.contents.block[0] = length
+ msg.data.contents.block[1:length + 1] = data
+ ioctl(self.fd, I2C_SMBUS, msg)
+
+ def block_process_call(self, i2c_addr, register, data, force=None):
+ """
+ Executes a SMBus Block Process Call, sending a variable-size data
+ block and receiving another variable-size response
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Register to read/write to
+ :type register: int
+ :param data: List of bytes
+ :type data: list
+ :param force:
+ :type force: Boolean
+ :return: List of bytes
+ :rtype: list
+ """
+ length = len(data)
+ if length > I2C_SMBUS_BLOCK_MAX:
+ raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX)
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_BLOCK_PROC_CALL
+ )
+ msg.data.contents.block[0] = length
+ msg.data.contents.block[1:length + 1] = data
+ ioctl(self.fd, I2C_SMBUS, msg)
+ length = msg.data.contents.block[0]
+ return msg.data.contents.block[1:length + 1]
+
+ def read_i2c_block_data(self, i2c_addr, register, length, force=None):
+ """
+ Read a block of byte data from a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Start register
+ :type register: int
+ :param length: Desired block length
+ :type length: int
+ :param force:
+ :type force: Boolean
+ :return: List of bytes
+ :rtype: list
+ """
+ if length > I2C_SMBUS_BLOCK_MAX:
+ raise ValueError("Desired block length over %d bytes" % I2C_SMBUS_BLOCK_MAX)
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_READ, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA
+ )
+ msg.data.contents.byte = length
+ ioctl(self.fd, I2C_SMBUS, msg)
+ return msg.data.contents.block[1:length + 1]
+
+ def write_i2c_block_data(self, i2c_addr, register, data, force=None):
+ """
+ Write a block of byte data to a given register.
+
+ :param i2c_addr: i2c address
+ :type i2c_addr: int
+ :param register: Start register
+ :type register: int
+ :param data: List of bytes
+ :type data: list
+ :param force:
+ :type force: Boolean
+ :rtype: None
+ """
+ length = len(data)
+ if length > I2C_SMBUS_BLOCK_MAX:
+ raise ValueError("Data length cannot exceed %d bytes" % I2C_SMBUS_BLOCK_MAX)
+ self._set_address(i2c_addr, force=force)
+ msg = i2c_smbus_ioctl_data.create(
+ read_write=I2C_SMBUS_WRITE, command=register, size=I2C_SMBUS_I2C_BLOCK_DATA
+ )
+ msg.data.contents.block[0] = length
+ msg.data.contents.block[1:length + 1] = data
+ ioctl(self.fd, I2C_SMBUS, msg)
+
+ def i2c_rdwr(self, *i2c_msgs):
+ """
+ Combine a series of i2c read and write operations in a single
+ transaction (with repeated start bits but no stop bits in between).
+
+ This method takes i2c_msg instances as input, which must be created
+ first with :py:meth:`i2c_msg.read` or :py:meth:`i2c_msg.write`.
+
+ :param i2c_msgs: One or more i2c_msg class instances.
+ :type i2c_msgs: i2c_msg
+ :rtype: None
+ """
+ ioctl_data = i2c_rdwr_ioctl_data.create(*i2c_msgs)
+ ioctl(self.fd, I2C_RDWR, ioctl_data)
+
+
+class SMBusWrapper:
+ """
+ Wrapper class around the SMBus.
+ Deprecated as of version 0.3.0. Please replace with :py:class:`SMBus`.
+
+ Enables the user to wrap access to the :py:class:`SMBus` class in a
+ "with" statement. If auto_cleanup is True (default), the
+ :py:class:`SMBus` handle will be automatically closed
+ upon exit of the ``with`` block.
+ """
+
+ def __init__(self, bus_number=0, auto_cleanup=True, force=False):
+ """
+ :param auto_cleanup: Close bus when leaving scope.
+ :type auto_cleanup: Boolean
+ :param force: Force using the slave address even when driver is already using it.
+ :type force: Boolean
+ """
+ self.bus_number = bus_number
+ self.auto_cleanup = auto_cleanup
+ self.force = force
+ self.bus = None
+
+ def __enter__(self):
+ self.bus = SMBus(bus=self.bus_number, force=self.force)
+ return self.bus
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ if self.auto_cleanup:
+ self.bus.close()
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modprobe_conf/kernel_drivers_blacklist.conf b/platform/broadcom/sonic-platform-modules-micas/common/modprobe_conf/kernel_drivers_blacklist.conf
new file mode 100644
index 000000000000..fea9ac508aaf
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modprobe_conf/kernel_drivers_blacklist.conf
@@ -0,0 +1,7 @@
+blacklist wb_fpga_pcie
+blacklist wb_i2c_i801
+blacklist wb_spi_gpio
+blacklist spi_intel
+blacklist spi_intel_platform
+blacklist wb_i2c_ismt
+blacklist spi_intel_pci
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/COPYING b/platform/broadcom/sonic-platform-modules-micas/common/modules/COPYING
new file mode 100644
index 000000000000..a635a38ef940
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/COPYING
@@ -0,0 +1,20 @@
+The Linux Kernel is provided under:
+
+ SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+
+Being under the terms of the GNU General Public License version 2 only,
+according with:
+
+ LICENSES/preferred/GPL-2.0
+
+With an explicit syscall exception, as stated at:
+
+ LICENSES/exceptions/Linux-syscall-note
+
+In addition, other licenses may also apply. Please see:
+
+ Documentation/process/license-rules.rst
+
+for more details.
+
+All contributions to the Linux Kernel are subject to this COPYING file.
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/GPL-2.0 b/platform/broadcom/sonic-platform-modules-micas/common/modules/GPL-2.0
new file mode 100644
index 000000000000..ff0812fd89cc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/GPL-2.0
@@ -0,0 +1,359 @@
+Valid-License-Identifier: GPL-2.0
+Valid-License-Identifier: GPL-2.0-only
+Valid-License-Identifier: GPL-2.0+
+Valid-License-Identifier: GPL-2.0-or-later
+SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
+Usage-Guide:
+ To use this license in source code, put one of the following SPDX
+ tag/value pairs into a comment according to the placement
+ guidelines in the licensing rules documentation.
+ For 'GNU General Public License (GPL) version 2 only' use:
+ SPDX-License-Identifier: GPL-2.0
+ or
+ SPDX-License-Identifier: GPL-2.0-only
+ For 'GNU General Public License (GPL) version 2 or any later version' use:
+ SPDX-License-Identifier: GPL-2.0+
+ or
+ SPDX-License-Identifier: GPL-2.0-or-later
+License-Text:
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/modules/Makefile
new file mode 100644
index 000000000000..63c4238836e7
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/Makefile
@@ -0,0 +1,63 @@
+PWD = $(shell pwd)
+EXTRA_CFLAGS:= -I$(M)/include
+EXTRA_CFLAGS+= -Wall
+KVERSION ?= $(shell uname -r)
+KERNEL_SRC ?= /lib/modules/$(KVERSION)
+
+module_out_put_dir := $(PWD)/build
+export module_out_put_dir
+
+KERNEL_MODULES_SRC = $(PWD)/linux-5.10
+
+PLAT_SYSFS_DIR = $(PWD)/plat_sysfs
+PHY = $(PWD)/phy
+PINCTRL = $(PWD)/pinctrl
+SDHCI = $(PWD)/sdhci
+RTL_DRIVER_PATH = r8168
+
+export PLAT_SYSFS_DIR
+
+platform_common-objs := platform_common_module.o dfd_tlveeprom.o
+obj-m += platform_common.o
+obj-m += wb_mac_bsc.o
+obj-m += wb_fpga_pcie.o
+obj-m += wb_pcie_dev.o
+obj-m += wb_fpga_i2c_bus_drv.o
+obj-m += wb_fpga_pca954x_drv.o
+obj-m += wb_lpc_drv.o
+obj-m += wb_i2c_dev.o
+obj-m += wb_platform_i2c_dev.o
+obj-m += wb_io_dev.o
+obj-m += wb_eeprom_93xx46.o
+#obj-m += wb_spi_93xx46.o
+obj-m += wb_gpio_d1500.o
+obj-m += wb_gpio_device.o
+obj-m += wb_i2c_ocores.o
+obj-m += wb_spi_ocores.o
+obj-m += wb_spi_dev.o
+obj-m += wb_wdt.o
+obj-m += wb_optoe.o
+obj-m += wb_spi_gpio.o
+obj-m += wb_spi_gpio_device.o
+#obj-m += wb_spi_nor_device.o
+obj-m += wb_xdpe132g5c.o
+obj-m += wb_uio_irq.o
+obj-m += hw_test.o
+obj-y += r8168/
+
+all :
+ $(MAKE) -C $(KERNEL_MODULES_SRC)
+ $(MAKE) -C $(PLAT_SYSFS_DIR)
+ $(MAKE) -C $(PHY)
+ $(MAKE) -C $(PINCTRL)
+ $(MAKE) -C $(SDHCI)
+ $(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules
+ @if [ ! -d $(module_out_put_dir) ]; then mkdir -p $(module_out_put_dir) ;fi
+ cp -p $(PWD)/*.ko $(module_out_put_dir)
+ cp -p $(PWD)/$(RTL_DRIVER_PATH)/*.ko $(module_out_put_dir)
+
+clean :
+ rm -rf $(module_out_put_dir)
+ rm -f ${PWD}/*.o ${PWD}/*.ko ${PWD}/*.mod.c ${PWD}/.*.cmd ${PWD}/.*.o.d ${PWD}/*.mod
+ rm -f ${PWD}/Module.markers ${PWD}/Module.symvers ${PWD}/modules.order
+ rm -rf ${PWD}/.tmp_versions
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.c
new file mode 100644
index 000000000000..0d6f38ecc551
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2003-2014 FreeIPMI Core Team
+ *
+ * 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 .
+ *
+ */
+/*****************************************************************************\
+ * Copyright (C) 2007-2014 Lawrence Livermore National Security, LLC.
+ * Copyright (C) 2007 The Regents of the University of California.
+ * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ * Written by Albert Chu
+ * UCRL-CODE-232183
+ *
+ * This file is part of Ipmi-fru, a tool used for retrieving
+ * motherboard field replaceable unit (FRU) information. For details,
+ * see http://www.llnl.gov/linux/.
+ *
+ * Ipmi-fru 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.
+ *
+ * Ipmi-fru 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 Ipmi-fru. If not, see .
+\*****************************************************************************/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "platform_common.h"
+#include "dfd_tlveeprom.h"
+
+/* using in is_valid_tlvinfo_header */
+static u_int32_t eeprom_size;
+
+/*
+ * List of TLV codes and names.
+ */
+static const struct tlv_code_desc tlv_code_list[] = {
+ { TLV_CODE_PRODUCT_NAME , "Product Name"},
+ { TLV_CODE_PART_NUMBER , "Part Number"},
+ { TLV_CODE_SERIAL_NUMBER , "Serial Number"},
+ { TLV_CODE_MAC_BASE , "Base MAC Address"},
+ { TLV_CODE_MANUF_DATE , "Manufacture Date"},
+ { TLV_CODE_DEVICE_VERSION , "Device Version"},
+ { TLV_CODE_LABEL_REVISION , "Label Revision"},
+ { TLV_CODE_PLATFORM_NAME , "Platform Name"},
+ { TLV_CODE_ONIE_VERSION , "ONIE Version"},
+ { TLV_CODE_MAC_SIZE , "MAC Addresses"},
+ { TLV_CODE_MANUF_NAME , "Manufacturer"},
+ { TLV_CODE_MANUF_COUNTRY , "Country Code"},
+ { TLV_CODE_VENDOR_NAME , "Vendor Name"},
+ { TLV_CODE_DIAG_VERSION , "Diag Version"},
+ { TLV_CODE_SERVICE_TAG , "Service Tag"},
+ { TLV_CODE_VENDOR_EXT , "Vendor Extension"},
+ { TLV_CODE_CRC_32 , "CRC-32"},
+};
+
+#if 0
+#define OPENBMC_VPD_KEY_INVAIL_VAL 0
+
+static const tlv_code_map_t tlv_code_map[] = {
+ { TLV_CODE_PRODUCT_NAME , OPENBMC_VPD_KEY_PRODUCT_NAME},
+ { TLV_CODE_PART_NUMBER , OPENBMC_VPD_KEY_PRODUCT_PART_MODEL_NUM},
+ { TLV_CODE_SERIAL_NUMBER , OPENBMC_VPD_KEY_PRODUCT_SERIAL_NUM},
+ { TLV_CODE_MAC_BASE , OPENBMC_VPD_KEY_INVAIL_VAL},
+ { TLV_CODE_MANUF_DATE , OPENBMC_VPD_KEY_BOARD_MFG_DATE},
+ { TLV_CODE_DEVICE_VERSION , OPENBMC_VPD_KEY_PRODUCT_VER},
+ { TLV_CODE_LABEL_REVISION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM7},
+ { TLV_CODE_PLATFORM_NAME , OPENBMC_VPD_KEY_PRODUCT_CUSTOM1},
+ { TLV_CODE_ONIE_VERSION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM2},
+ { TLV_CODE_MAC_SIZE , OPENBMC_VPD_KEY_INVAIL_VAL},
+ { TLV_CODE_MANUF_NAME , OPENBMC_VPD_KEY_PRODUCT_MFR},
+ { TLV_CODE_MANUF_COUNTRY , OPENBMC_VPD_KEY_PRODUCT_CUSTOM3},
+ { TLV_CODE_VENDOR_NAME , OPENBMC_VPD_KEY_PRODUCT_CUSTOM4},
+ { TLV_CODE_DIAG_VERSION , OPENBMC_VPD_KEY_PRODUCT_CUSTOM8},
+ { TLV_CODE_SERVICE_TAG , OPENBMC_VPD_KEY_PRODUCT_CUSTOM5},
+ { TLV_CODE_VENDOR_EXT , OPENBMC_VPD_KEY_PRODUCT_CUSTOM6},
+ { TLV_CODE_CRC_32 , OPENBMC_VPD_KEY_INVAIL_VAL},
+};
+#endif
+
+#define TLV_CODE_NUM (sizeof(tlv_code_list) / sizeof(tlv_code_list[0]))
+
+#if 0
+#define TLV_CODE_MAP_NUM (sizeof(tlv_code_map) / sizeof(tlv_code_map[0]))
+#endif
+
+const unsigned long crc_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+static unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned len)
+{
+ unsigned i;
+ if (len < 1)
+ return 0xffffffff;
+
+ for (i = 0; i != len; ++i)
+ {
+ crc = crc_table[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
+ }
+
+ crc = crc ^ 0xffffffff;
+
+ return crc;
+}
+
+/*
+ * is_valid_tlv
+ *
+ * Perform basic sanity checks on a TLV field. The TLV is pointed to
+ * by the parameter provided.
+ * 1. The type code is not reserved (0x00 or 0xFF)
+ */
+static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv)
+{
+ return ((tlv->type != 0x00) && (tlv->type != 0xFF));
+}
+
+/*
+ * is_valid_tlvinfo_header
+ *
+ * Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM
+ * data pointed to by the parameter:
+ * 1. First 8 bytes contain null-terminated ASCII string "TlvInfo"
+ * 2. Version byte is 1
+ * 3. Total length bytes contain value which is less than or equal
+ * to the allowed maximum (2048-11)
+ *
+ */
+static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr)
+{
+ int max_size = eeprom_size;
+ return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) &&
+ (hdr->version == TLV_INFO_VERSION) &&
+ (be16_to_cpu(hdr->totallen) <= max_size) );
+}
+
+/*
+ * decode_tlv_value
+ *
+ * Decode a single TLV value into a string.
+
+ * The validity of EEPROM contents and the TLV field have been verified
+ * prior to calling this function.
+ */
+static void decode_tlv_value(tlvinfo_tlv_t *tlv, tlv_decode_value_t *decode_value)
+{
+ int i;
+ char *value;
+ u_int32_t length;
+
+ value = (char *)decode_value->value;
+
+ switch (tlv->type) {
+ case TLV_CODE_PRODUCT_NAME:
+ case TLV_CODE_PART_NUMBER:
+ case TLV_CODE_SERIAL_NUMBER:
+ case TLV_CODE_MANUF_DATE:
+ case TLV_CODE_LABEL_REVISION:
+ case TLV_CODE_PLATFORM_NAME:
+ case TLV_CODE_ONIE_VERSION:
+ case TLV_CODE_MANUF_NAME:
+ case TLV_CODE_MANUF_COUNTRY:
+ case TLV_CODE_VENDOR_NAME:
+ case TLV_CODE_DIAG_VERSION:
+ case TLV_CODE_SERVICE_TAG:
+ case TLV_CODE_VENDOR_EXT:
+ memcpy(value, tlv->value, tlv->length);
+ value[tlv->length] = 0;
+ length = tlv->length;
+ break;
+ case TLV_CODE_MAC_BASE:
+ length = sprintf(value, "%02X:%02X:%02X:%02X:%02X:%02X",
+ tlv->value[0], tlv->value[1], tlv->value[2],
+ tlv->value[3], tlv->value[4], tlv->value[5]);
+ break;
+ case TLV_CODE_DEVICE_VERSION:
+ length = sprintf(value, "%u", tlv->value[0]);
+ break;
+ case TLV_CODE_MAC_SIZE:
+ length = sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]);
+ break;
+ #if 0
+ case TLV_CODE_VENDOR_EXT:
+ value[0] = 0;
+ length = 0;
+ for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) {
+ length += sprintf(value, "%s 0x%02X", value, tlv->value[i]);
+ }
+ break;
+ #endif
+ case TLV_CODE_CRC_32:
+ length = sprintf(value, "0x%02X%02X%02X%02X", tlv->value[0],
+ tlv->value[1], tlv->value[2], tlv->value[3]);
+ break;
+ default:
+ value[0] = 0;
+ length = 0;
+ for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length); i++) {
+ length += sprintf(value, "%s 0x%02X", value, tlv->value[i]);
+ }
+ break;
+ }
+
+ decode_value->length = length;
+}
+
+/*
+ * is_checksum_valid
+ *
+ * Validate the checksum in the provided TlvInfo EEPROM data. First,
+ * verify that the TlvInfo header is valid, then make sure the last
+ * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data
+ * and compare it to the value stored in the EEPROM CRC-32 TLV.
+ */
+static bool is_checksum_valid(u_int8_t *eeprom)
+{
+ tlvinfo_header_t *eeprom_hdr;
+ tlvinfo_tlv_t *eeprom_crc;
+ unsigned int calc_crc;
+ unsigned int stored_crc;
+
+ eeprom_hdr = (tlvinfo_header_t *) eeprom;
+
+ // Is the eeprom header valid?
+ if (!is_valid_tlvinfo_header(eeprom_hdr)) {
+ return false;
+ }
+
+ // Is the last TLV a CRC?
+ eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) +
+ be16_to_cpu(eeprom_hdr->totallen) - (sizeof(tlvinfo_tlv_t) + 4)];
+ if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) {
+ return false;
+ }
+
+ // Calculate the checksum
+ calc_crc = crc32(0xffffffffL, (const unsigned char *)eeprom, sizeof(tlvinfo_header_t) +
+ be16_to_cpu(eeprom_hdr->totallen) - 4);
+ stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) |
+ (eeprom_crc->value[2] << 8) | eeprom_crc->value[3]);
+
+ return (calc_crc == stored_crc);
+}
+
+/*
+ * tlvinfo_find_tlv
+ *
+ * This function finds the TLV with the supplied code in the EERPOM.
+ * An offset from the beginning of the EEPROM is returned in the
+ * eeprom_index parameter if the TLV is found.
+ */
+static bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index)
+{
+ tlvinfo_header_t *eeprom_hdr;
+ tlvinfo_tlv_t *eeprom_tlv;
+ int eeprom_end;
+
+ eeprom_hdr = (tlvinfo_header_t *) eeprom;
+
+ // Search through the TLVs, looking for the first one which matches the
+ // supplied type code.
+ *eeprom_index = sizeof(tlvinfo_header_t);
+ eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen);
+ while (*eeprom_index < eeprom_end) {
+ eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index];
+ if (!is_valid_tlv(eeprom_tlv)) {
+ return false;
+ }
+
+ if (eeprom_tlv->type == tcode) {
+ return true;
+ }
+
+ *eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length;
+ }
+
+ return false;
+}
+
+/*
+ * tlvinfo_decode_tlv
+ *
+ * This function finds the TLV with the supplied code in the EERPOM
+ * and decodes the value into the buffer provided.
+ */
+static bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, tlv_decode_value_t *decode_value)
+{
+ int eeprom_index;
+ tlvinfo_tlv_t *eeprom_tlv;
+
+ // Find the TLV and then decode it
+ if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) {
+ eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index];
+ decode_tlv_value(eeprom_tlv, decode_value);
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * parse_tlv_eeprom
+ *
+ * parse the EEPROM into memory, if it hasn't already been read.
+ */
+int parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size)
+{
+ unsigned int i;
+ bool ret;
+ tlvinfo_header_t *eeprom_hdr;
+ //tlv_info_vec_t tlv_info;
+ tlv_decode_value_t decode_value;
+ int j;
+
+ eeprom_hdr = (tlvinfo_header_t *) eeprom;
+ eeprom_size = size; /* eeprom real size */
+
+ if (!is_valid_tlvinfo_header(eeprom_hdr)) {
+ DBG_ERROR("Failed to check tlv header.\n");
+ return -1;
+ }
+
+ if (!is_checksum_valid(eeprom)) {
+ DBG_ERROR("Failed to check tlv crc.\n");
+ return -1;
+ }
+
+ for (i = 0; i < TLV_CODE_NUM; i++) {
+ mem_clear((void *)&decode_value, sizeof(tlv_decode_value_t));
+ ret = tlvinfo_decode_tlv(eeprom, tlv_code_list[i].m_code, &decode_value);
+ if (!ret) {
+ DBG_ERROR("No found type: %s\n", tlv_code_list[i].m_name);
+ continue;
+ }
+
+ DBG_DEBUG("i: %d,Found type: %s tlv[%d]:%s\n", i, tlv_code_list[i].m_name, tlv_code_list[i].m_code,
+ decode_value.value);
+ for (j = 0; j < decode_value.length; j++) {
+ if ((j % 16) == 0) {
+ DBG_DEBUG("\n");
+ }
+ DBG_DEBUG("%02x ", decode_value.value[j]);
+ }
+ DBG_DEBUG("\n\n");
+ }
+ return 0;
+}
+static int dfd_parse_tlv_eeprom(u_int8_t *eeprom, u_int32_t size, u_int8_t main_type, tlv_decode_value_t *decode_value)
+{
+ bool ret;
+ tlvinfo_header_t *eeprom_hdr;
+ //tlv_info_vec_t tlv_info;
+ int j;
+
+ eeprom_hdr = (tlvinfo_header_t *) eeprom;
+ eeprom_size = size; /* eeprom real size */
+
+ if (!is_valid_tlvinfo_header(eeprom_hdr)) {
+ DBG_ERROR("Failed to check tlv header.\n");
+ return -1;
+ }
+
+ if (!is_checksum_valid(eeprom)) {
+ DBG_ERROR("Failed to check tlv crc.\n");
+ return -1;
+ }
+
+ ret = tlvinfo_decode_tlv(eeprom, main_type, decode_value);
+ if (!ret) {
+ DBG_ERROR("No found type: %d\n", main_type);
+ return -1;
+ }
+
+ DBG_DEBUG("Found type: %d, value: %s\n", main_type,decode_value->value);
+ for (j = 0; j < decode_value->length; j++) {
+ if ((j % 16) == 0) {
+ DBG_DEBUG("\n");
+ }
+ DBG_DEBUG("%02x ", decode_value->value[j]);
+ }
+ DBG_DEBUG("\n\n");
+
+ return 0;
+}
+
+static int tlvinfo_find_wb_ext_tlv(tlv_decode_value_t *ext_tlv_value, u_int8_t ext_type,
+ u_int8_t *buf, u_int8_t *buf_len)
+{
+ tlvinfo_tlv_t *eeprom_tlv;
+ int eeprom_end, eeprom_index;
+
+ // Search through the TLVs, looking for the first one which matches the
+ // supplied type code.
+ DBG_DEBUG("ext_tlv_value->length: %d.\n", ext_tlv_value->length);
+ for (eeprom_index = 0; eeprom_index < ext_tlv_value->length; eeprom_index++) {
+ if ((eeprom_index % 16) == 0) {
+ DBG_DEBUG("\n");
+ }
+ DBG_DEBUG("%02x ", ext_tlv_value->value[eeprom_index]);
+ }
+
+ DBG_DEBUG("\n");
+
+ eeprom_index = 0;
+ eeprom_end = ext_tlv_value->length;
+ while (eeprom_index < eeprom_end) {
+ eeprom_tlv = (tlvinfo_tlv_t *) &(ext_tlv_value->value[eeprom_index]);
+ if (!is_valid_tlv(eeprom_tlv)) {
+ DBG_ERROR("tlv is not valid, eeprom_tlv->type 0x%x.\n", eeprom_tlv->type);
+ return -1;
+ }
+
+ DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length);
+ if (eeprom_tlv->type == ext_type) {
+ if (*buf_len >= eeprom_tlv->length) {
+ memcpy(buf, eeprom_tlv->value, eeprom_tlv->length);
+ DBG_DEBUG("eeprom_tlv->length %d.\n", eeprom_tlv->length);
+ *buf_len = eeprom_tlv->length;
+ return 0;
+ }
+ DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, eeprom_tlv->length);
+ return -1;
+ }
+
+ eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length;
+ }
+
+ DBG_ERROR("ext_type %d: tlv is not found.\n", ext_type);
+ return -1;
+}
+
+int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len)
+{
+ tlv_decode_value_t decode_value;
+ int ret;
+
+ if (eeprom == NULL || tlv_type == NULL || buf == NULL) {
+ DBG_ERROR("Input para invalid.\n");
+ return -1;
+ }
+
+ mem_clear((void *)&decode_value, sizeof(tlv_decode_value_t));
+ ret = dfd_parse_tlv_eeprom(eeprom, size, tlv_type->main_type, &decode_value);
+ if (ret) {
+ DBG_ERROR("dfd_parse_tlv_eeprom failed ret %d.\n", ret);
+ return ret;
+ }
+
+ if (tlv_type->main_type != TLV_CODE_VENDOR_EXT) {
+ if (*buf_len >= decode_value.length) {
+ memcpy(buf, decode_value.value, decode_value.length);
+ *buf_len = decode_value.length;
+ return 0;
+ }
+ DBG_ERROR("buf_len %d small than info_len %d.\n", *buf_len, decode_value.length);
+ return -1;
+ }
+ DBG_DEBUG("info_len %d.\n", decode_value.length);
+
+ return tlvinfo_find_wb_ext_tlv(&decode_value, tlv_type->ext_type, buf, buf_len);
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.h
new file mode 100644
index 000000000000..6eaac5848223
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.h
@@ -0,0 +1,121 @@
+#ifndef DFD_OPENBMC_TLVEEPROM_H
+#define DFD_OPENBMC_TLVEEPROM_H
+
+#ifndef u_int8_t
+#define u_int8_t unsigned char
+#endif
+
+#ifndef u_int16_t
+#define u_int16_t unsigned short
+#endif
+
+#ifndef u_int32_t
+#define u_int32_t unsigned int
+#endif
+
+#ifndef be16_to_cpu
+#define be16_to_cpu(x) ntohs(x)
+#endif
+
+#ifndef cpu_to_be16
+#define cpu_to_be16(x) htons(x)
+#endif
+
+/**
+ * The TLV Types.
+ *
+ * Keep these in sync with tlv_code_list in cmd_sys_eeprom.c
+ */
+#define TLV_CODE_PRODUCT_NAME 0x21
+#define TLV_CODE_PART_NUMBER 0x22
+#define TLV_CODE_SERIAL_NUMBER 0x23
+#define TLV_CODE_MAC_BASE 0x24
+#define TLV_CODE_MANUF_DATE 0x25
+#define TLV_CODE_DEVICE_VERSION 0x26
+#define TLV_CODE_LABEL_REVISION 0x27
+#define TLV_CODE_PLATFORM_NAME 0x28
+#define TLV_CODE_ONIE_VERSION 0x29
+#define TLV_CODE_MAC_SIZE 0x2A
+#define TLV_CODE_MANUF_NAME 0x2B
+#define TLV_CODE_MANUF_COUNTRY 0x2C
+#define TLV_CODE_VENDOR_NAME 0x2D
+#define TLV_CODE_DIAG_VERSION 0x2E
+#define TLV_CODE_SERVICE_TAG 0x2F
+#define TLV_CODE_VENDOR_EXT 0xFD
+#define TLV_CODE_CRC_32 0xFE
+
+#define TLV_CODE_NAME_LEN 64
+/*
+ * Struct for displaying the TLV codes and names.
+ */
+struct tlv_code_desc {
+ u_int8_t m_code;
+ char m_name[TLV_CODE_NAME_LEN];
+};
+
+typedef struct dfd_tlv_type_s {
+ u_int8_t main_type;
+ u_int8_t ext_type;
+} dfd_tlv_type_t;
+
+// Header Field Constants
+#define TLV_INFO_ID_STRING "TlvInfo"
+#define TLV_INFO_VERSION 0x01
+/*#define TLV_TOTAL_LEN_MAX (XXXXXXXX - sizeof(tlvinfo_header_t))*/
+
+struct __attribute__ ((__packed__)) tlvinfo_header_s {
+ char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */
+ u_int8_t version; /* 0x08 Structure version */
+ u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */
+};
+typedef struct tlvinfo_header_s tlvinfo_header_t;
+
+/*
+ * TlvInfo TLV: Layout of a TLV field
+ */
+struct __attribute__ ((__packed__)) tlvinfo_tlv_s {
+ u_int8_t type;
+ u_int8_t length;
+ u_int8_t value[0];
+};
+typedef struct tlvinfo_tlv_s tlvinfo_tlv_t;
+
+#define TLV_VALUE_MAX_LEN 255
+/*
+ * The max decode value is currently for the 'raw' type or the 'vendor
+ * extension' type, both of which have the same decode format. The
+ * max decode string size is computed as follows:
+ *
+ * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1
+ *
+ */
+#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1)
+
+typedef struct tlv_decode_value_s {
+ u_int8_t value[TLV_DECODE_VALUE_MAX_LEN];
+ u_int32_t length;
+} tlv_decode_value_t;
+
+typedef enum dfd_tlvinfo_ext_tlv_type_e {
+ DFD_TLVINFO_EXT_TLV_TYPE_DEV_TYPE = 1,
+} dfd_tlvinfo_ext_tlv_type_t;
+
+#if 0
+#define TLV_TIME_LEN 64
+
+int ipmi_tlv_validate_fru_area(const uint8_t fruid, const char *fru_file_name,
+ sd_bus *bus_type, const bool bmc_fru);
+
+extern const char *get_vpd_key_names(int key_id);
+extern std::string getService(sdbusplus::bus::bus& bus,
+ const std::string& intf,
+ const std::string& path);
+extern std::string getFRUValue(const std::string& section,
+ const std::string& key,
+ const std::string& delimiter,
+ IPMIFruInfo& fruData);
+#endif
+
+int dfd_tlvinfo_get_e2prom_info(u_int8_t *eeprom, u_int32_t size, dfd_tlv_type_t *tlv_type, u_int8_t* buf, u_int8_t *buf_len);
+
+#endif /* endif DFD_OPENBMC_TLVEEPROM_H */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/fpga_i2c.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/fpga_i2c.h
new file mode 100644
index 000000000000..649a8452debe
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/fpga_i2c.h
@@ -0,0 +1,133 @@
+#ifndef _FPGA_I2C_H
+#define _FPGA_I2C_H
+
+#include
+#include
+#include
+#include
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+#if 0
+
+#define FPGA_I2C_EXT_9548_ADDR (0x00)
+#define FPGA_I2C_EXT_9548_CHAN (0x04)
+#define FPGA_I2C_DEV_SLAVE_ADDR (0x08)
+#define FPGA_I2C_DEV_REG_ADDR (0x0C)
+#define FPGA_I2C_DEV_RDWR_LEN (0x10)
+#define FPGA_I2C_CTRL_REG (0x14)
+#define FPGA_I2C_STATUS_REG (0x18)
+#define FPGA_I2C_SCALE_REG (0x1C)
+#define FPGA_I2C_FILTER_REG (0x20)
+#define FPGA_I2C_STRETCH_REG (0x24)
+#define FPGA_I2C_EXT_9548_EXITS_FLAG (0x28)
+#define FPGA_I2C_INTERNAL_9548_CHAN (0x2C)
+#define FPGA_I2C_RDWR_DATA_BUF (0x80)
+#endif
+#define FPGA_I2C_RDWR_MAX_LEN_DEFAULT (128)
+#define I2C_REG_MAX_WIDTH (16)
+
+#define DEV_NAME_MAX_LEN (64)
+
+#define FPGA_I2C_MAX_TIMES (10)
+#define FPGA_I2C_XFER_TIME_OUT (100000)
+#define FPGA_I2C_SLEEP_TIME (40)
+
+typedef struct fpga_i2c_reg_s {
+ uint32_t i2c_scale;
+ uint32_t i2c_filter;
+ uint32_t i2c_stretch;
+ uint32_t i2c_ext_9548_exits_flag;
+ uint32_t i2c_ext_9548_addr;
+ uint32_t i2c_ext_9548_chan;
+ uint32_t i2c_in_9548_chan;
+ uint32_t i2c_slave;
+ uint32_t i2c_reg;
+ uint32_t i2c_reg_len;
+ uint32_t i2c_data_len;
+ uint32_t i2c_ctrl;
+ uint32_t i2c_status;
+ uint32_t i2c_err_vec;
+ uint32_t i2c_data_buf;
+ uint32_t i2c_data_buf_len;
+} fpga_i2c_reg_t;
+
+typedef struct fpga_i2c_reset_cfg_s {
+ uint32_t i2c_adap_reset_flag;
+ uint32_t reset_addr;
+ uint32_t reset_on;
+ uint32_t reset_off;
+ uint32_t reset_delay_b;
+ uint32_t reset_delay;
+ uint32_t reset_delay_a;
+} fpga_i2c_reset_cfg_t;
+
+typedef struct fpga_i2c_reg_addr_s {
+ uint8_t reg_addr_len;
+ uint8_t read_reg_addr[I2C_REG_MAX_WIDTH];
+} fpga_i2c_reg_addr_t;
+
+typedef struct fpga_i2c_dev_s {
+ fpga_i2c_reg_t reg;
+ fpga_i2c_reset_cfg_t reset_cfg;
+ fpga_i2c_reg_addr_t i2c_addr_desc;
+ const char *dev_name;
+ uint32_t i2c_scale_value;
+ uint32_t i2c_filter_value;
+ uint32_t i2c_stretch_value;
+ uint32_t i2c_timeout;
+ uint32_t i2c_func_mode;
+ wait_queue_head_t queue;
+ struct i2c_adapter adap;
+ int adap_nr;
+ struct device *dev;
+ bool i2c_params_check;
+} fpga_i2c_dev_t;
+
+typedef struct fpga_i2c_bus_device_s {
+ int i2c_timeout;
+ int i2c_scale;
+ int i2c_filter;
+ int i2c_stretch;
+ int i2c_ext_9548_exits_flag;
+ int i2c_ext_9548_addr;
+ int i2c_ext_9548_chan;
+ int i2c_in_9548_chan;
+ int i2c_slave;
+ int i2c_reg;
+ int i2c_reg_len;
+ int i2c_data_len;
+ int i2c_ctrl;
+ int i2c_status;
+ int i2c_err_vec;
+ int i2c_data_buf;
+ int i2c_data_buf_len;
+ char dev_name[DEV_NAME_MAX_LEN];
+ int adap_nr;
+ int i2c_scale_value;
+ int i2c_filter_value;
+ int i2c_stretch_value;
+ int i2c_func_mode;
+ int i2c_adap_reset_flag;
+ int i2c_reset_addr;
+ int i2c_reset_on;
+ int i2c_reset_off;
+ int i2c_rst_delay_b; /* delay time before reset(us) */
+ int i2c_rst_delay; /* reset time(us) */
+ int i2c_rst_delay_a; /* delay time after reset(us) */
+ int device_flag;
+ bool i2c_params_check;
+ int i2c_data_buf_len_reg;
+ int i2c_offset_reg;
+} fpga_i2c_bus_device_t;
+
+typedef struct fpga_pca954x_device_s {
+ struct i2c_client *client;
+ uint32_t i2c_bus;
+ uint32_t i2c_addr;
+ uint32_t fpga_9548_flag;
+ uint32_t fpga_9548_reset_flag;
+ uint32_t pca9548_base_nr;
+} fpga_pca954x_device_t;
+
+#endif /* _FPGA_I2C_H */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.c
new file mode 100644
index 000000000000..e74f4e800582
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.c
@@ -0,0 +1,608 @@
+/*
+ * hw_test.c
+ * Original Author : support, 2020-10-15
+ *
+ * History
+ * v1.0 support 2020-10-15 Initial version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "hw_test.h"
+
+extern struct bus_type mdio_bus_type;
+
+struct board_mdio_dev {
+ struct list_head list;
+ struct mii_bus *mdio_bus;
+ int mdio_index;
+};
+
+struct board_phy_dev {
+ struct list_head list;
+ struct phy_device *phydev;
+ int phy_index;
+};
+
+static LIST_HEAD(mdio_dev_list);
+static LIST_HEAD(phydev_list);
+static struct class *class_mdio_bus = NULL;
+
+#define PRINT_BUF_SIZE (256)
+#define INVALID_PHY_ADDR (0xFF)
+#define MAX_MDIO_DEVICE_NUMS (1000)
+#define MAX_PHY_DEVICE_NUMS (1000)
+
+#define dram_debug(fmt, ...) \
+ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+
+static ssize_t dram_dev_read (struct file *file, char __user *buf, size_t count,
+ loff_t *offset)
+{
+ u8 value8;
+ u16 value16;
+ u32 value32;
+
+ if (file->private_data != NULL) {
+ return -EINVAL;
+ }
+
+ file->private_data = ioremap(file->f_pos, count);
+
+ if (!file->private_data) {
+ pr_notice("%s, %d\n", __FUNCTION__, __LINE__);
+ return -ENODEV;
+ }
+
+ rmb();
+ switch (count) {
+ case 1:
+ value8 = readb(file->private_data);
+ if (copy_to_user(buf, &value8, sizeof(u8))) {
+ return -EFAULT;
+ }
+ break;
+ case 2:
+ value16 = readw(file->private_data);
+ if (copy_to_user(buf, &value16, sizeof(u16))) {
+ return -EFAULT;
+ }
+ break;
+ case 4:
+ value32 = readl(file->private_data);
+ if (copy_to_user(buf, &value32, sizeof(u32))) {
+ return -EFAULT;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ iounmap(file->private_data);
+ file->private_data = NULL;
+ return count;
+
+}
+
+static ssize_t dram_dev_write (struct file *file, const char __user *buf, size_t count,
+ loff_t *offset)
+{
+ u8 value8;
+ u16 value16;
+ u32 value32;
+
+ if (file->private_data != NULL) {
+ return -EINVAL;
+ }
+
+ file->private_data = ioremap(file->f_pos, count);
+
+ if (!file->private_data) {
+ pr_err("%s, %d\n", __FUNCTION__, __LINE__);
+ return -ENODEV;
+ }
+
+ switch (count) {
+ case 1:
+ if (copy_from_user(&value8, buf, sizeof(u8))) {
+ return -EFAULT;
+ }
+ writeb(value8, file->private_data);
+ break;
+ case 2:
+ if (copy_from_user(&value16, buf, sizeof(u16))) {
+ return -EFAULT;
+ }
+ writew(value16, file->private_data);
+ break;
+ case 4:
+ if (copy_from_user(&value32, buf, sizeof(u32))) {
+ return -EFAULT;
+ }
+ writel(value32, file->private_data);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ wmb();
+ iounmap(file->private_data);
+ file->private_data = NULL;
+ return count;
+}
+
+static loff_t dram_dev_llseek(struct file *file, loff_t offset, int origin)
+{
+ loff_t ret;
+
+ switch (origin) {
+ case 0:
+ file->f_pos = offset;
+ ret = file->f_pos;
+ break;
+ case 1:
+ file->f_pos += offset;
+ ret = file->f_pos;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int temp_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+{
+ return 0;
+}
+
+static int temp_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value)
+{
+ return 0;
+}
+
+static int init_class_mdio_bus(void)
+{
+ struct mii_bus *bus;
+ int err = 0;
+
+ bus = mdiobus_alloc();
+
+ bus->name = "temp_mdio_bus";
+ snprintf(bus->id, MII_BUS_ID_SIZE, "temp_mdio_bus0");
+ bus->read = temp_mdiobus_read;
+ bus->write = temp_mdiobus_write;
+
+ err = mdiobus_register(bus);
+ if (err) {
+ printk(KERN_ERR "temp mdio bus register fail\n");
+ return -1;
+ }
+
+ class_mdio_bus = bus->dev.class;
+ mdiobus_unregister(bus);
+
+ return 0;
+}
+
+static int mdio_match_success(struct device *dev, const void * data)
+{
+
+ return 1;
+}
+
+static int add_all_mdio_devices_to_list(void)
+{
+ struct device *dev, *dev_start = NULL;
+ struct board_mdio_dev *mdio_dev = NULL;
+ int i = 0;
+ struct class *bus_class = class_mdio_bus;
+
+ for (i = 0; i < MAX_MDIO_DEVICE_NUMS; i++) {
+ dev = class_find_device(bus_class, dev_start, NULL, mdio_match_success);
+ if (dev != NULL) {
+ mdio_dev = kzalloc(sizeof(struct board_mdio_dev), GFP_KERNEL);
+ if (mdio_dev == NULL) {
+ printk(KERN_ERR "%s: alloc fail\n", __func__);
+ return -EFAULT;
+ }
+
+ mdio_dev->mdio_index = i;
+ mdio_dev->mdio_bus = to_mii_bus(dev);
+ list_add_tail(&mdio_dev->list, &mdio_dev_list);
+
+ dev_start = dev;
+ } else {
+ break;
+ }
+ }
+
+ printk(KERN_INFO "mdio dev numbers = %d\n", i);
+
+ return 0;
+}
+
+static void delete_all_mdio_devices_from_list(void)
+{
+ struct list_head *n, *pos;
+ struct board_mdio_dev *mdio_dev;
+
+ list_for_each_safe(pos, n, &mdio_dev_list) {
+ list_del(pos);
+ mdio_dev = list_entry(pos, struct board_mdio_dev, list);
+ kfree(mdio_dev);
+ }
+
+ return;
+}
+
+void list_all_mdio_devices_info(void)
+{
+ struct board_mdio_dev *mdio_dev;
+ unsigned char phyaddr[PHY_MAX_ADDR];
+ int i = 0, j = 0;
+ int phydev_num = 0;
+ char buf[PRINT_BUF_SIZE];
+ int len = 0;
+
+ printk(KERN_INFO "all the mdio devs info:\n");
+ printk(KERN_INFO "index busid name phy_num phyaddr \n");
+ list_for_each_entry(mdio_dev, &mdio_dev_list, list) {
+ i = 0;
+ j = 0;
+ phydev_num = 0;
+ mem_clear(phyaddr, INVALID_PHY_ADDR, sizeof(phyaddr));
+ mem_clear(buf, 0, sizeof(buf));
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if (mdio_dev->mdio_bus->mdio_map[i]) {
+ phydev_num++;
+ phyaddr[j] = (unsigned char)i;
+ j++;
+ }
+ }
+
+ len = snprintf(buf, sizeof(buf), " %-10d %-20s %-20s %-10d ", mdio_dev->mdio_index,
+ mdio_dev->mdio_bus->id, mdio_dev->mdio_bus->name, phydev_num);
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+ if (phyaddr[i] == INVALID_PHY_ADDR) {
+ break;
+ }
+
+ len += snprintf(&buf[len], sizeof(buf) - len, " %#x", phyaddr[i]);
+ }
+
+ printk(KERN_INFO "%s\n", buf);
+ }
+
+ return;
+}
+
+static struct mii_bus *get_mdio_dev_according_to_index(int mdio_index)
+{
+ struct board_mdio_dev *mdio_dev;
+ list_for_each_entry(mdio_dev, &mdio_dev_list, list) {
+ if (mdio_dev->mdio_index == mdio_index) {
+ return mdio_dev->mdio_bus;
+ }
+ }
+
+ printk(KERN_ERR "no exist the mdio dev it's mdio_index = %d, please exec cmd [hw_test.bin mdiodev_list] to view mdiodev info\n",
+ mdio_index);
+
+ return NULL;
+}
+
+int board_mdio_read(int mdio_index, int phyaddr, u32 regnum)
+{
+ struct mii_bus *bus;
+ int reg_val;
+
+ bus = get_mdio_dev_according_to_index(mdio_index);
+ if (bus == NULL) {
+ return -1;
+ }
+
+ reg_val = mdiobus_read(bus, phyaddr, regnum);
+
+ return reg_val;
+}
+
+int board_mdio_write(int mdio_index, int phyaddr, u32 regnum, u16 val)
+{
+ struct mii_bus *bus;
+ int ret;
+
+ bus = get_mdio_dev_according_to_index(mdio_index);
+ if (bus == NULL) {
+ return -1;
+ }
+
+ ret = mdiobus_write(bus, phyaddr, regnum, val);
+
+ return ret;
+}
+
+static int phy_match_success(struct device *dev, const void * data)
+{
+
+ return 1;
+}
+
+static int add_all_phydevs_to_list(void)
+{
+ struct device *dev, *dev_start = NULL;
+ struct board_phy_dev *board_phydev = NULL;
+ int i = 0;
+
+ for (i = 0; i < MAX_PHY_DEVICE_NUMS; i++) {
+ dev = bus_find_device(&mdio_bus_type, dev_start, NULL, phy_match_success);
+ if (dev != NULL) {
+ board_phydev = kzalloc(sizeof(struct board_phy_dev), GFP_KERNEL);
+ if (board_phydev == NULL) {
+ printk(KERN_ERR "%s: alloc fail\n", __func__);
+ return -EFAULT;
+ }
+
+ board_phydev->phy_index = i;
+ board_phydev->phydev = to_phy_device(dev);
+ list_add_tail(&board_phydev->list, &phydev_list);
+
+ dev_start = dev;
+ } else {
+ break;
+ }
+ }
+
+ printk(KERN_INFO "phydev num = %d\n", i);
+
+ return 0;
+}
+
+static void delete_all_phydevs_from_list(void)
+{
+ struct list_head *n, *pos;
+ struct board_phy_dev *board_phydev;
+
+ list_for_each_safe(pos, n, &phydev_list) {
+ list_del(pos);
+ board_phydev = list_entry(pos, struct board_phy_dev, list);
+ kfree(board_phydev);
+ }
+
+ return;
+}
+
+void list_all_phydevs_info(void)
+{
+ struct board_phy_dev *board_phydev;
+
+ printk(KERN_INFO "all the phydevs info:\n");
+ printk(KERN_INFO "index phyaddr phyId phydev_name\n");
+ list_for_each_entry(board_phydev, &phydev_list, list) {
+ printk(KERN_INFO " %-10d %#-10x %#-10x %-20s\n", board_phydev->phy_index, board_phydev->phydev->mdio.addr,\
+ board_phydev->phydev->phy_id, dev_name(&board_phydev->phydev->mdio.dev));
+ }
+
+ return;
+}
+
+static struct phy_device *get_phy_dev_according_to_index(int phy_index)
+{
+ struct board_phy_dev *board_phydev;
+ list_for_each_entry(board_phydev, &phydev_list, list) {
+ if (board_phydev->phy_index == phy_index) {
+ return board_phydev->phydev;
+ }
+ }
+
+ printk(KERN_ERR "no exist the phydev it's phy_index = %d, please exec cmd [hw_test.bin phydev_list] to view phydev info\n", phy_index);
+
+ return NULL;
+}
+
+int board_phy_read(int phy_index, u32 regnum)
+{
+ struct phy_device *phydev;
+ int reg_val;
+
+ phydev = get_phy_dev_according_to_index(phy_index);
+ if (phydev == NULL) {
+ return -1;
+ }
+
+ reg_val = phy_read(phydev, regnum);
+
+ return reg_val;
+}
+
+int board_phy_write(int phy_index, u32 regnum, u16 val)
+{
+ struct phy_device *phydev;
+ int ret;
+
+ phydev = get_phy_dev_according_to_index(phy_index);
+ if (phydev == NULL) {
+ return -1;
+ }
+
+ ret = phy_write(phydev, regnum, val);
+
+ return ret;
+}
+
+static long dram_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int ret = 0;
+ struct phydev_user_info phy_user_info;
+ struct mdio_dev_user_info mdio_user_info;
+
+ switch (cmd) {
+ case CMD_PHY_LIST:
+ list_all_phydevs_info();
+ break;
+
+ case CMD_PHY_READ:
+ if (copy_from_user(&phy_user_info, argp, sizeof(struct phydev_user_info)))
+ return -EFAULT;
+
+ ret = board_phy_read(phy_user_info.phy_index, phy_user_info.regnum);
+ if (ret < 0) {
+ return -EFAULT;
+ }
+
+ phy_user_info.regval = (u32)ret;
+
+ if (copy_to_user(argp, &phy_user_info, sizeof(struct phydev_user_info)))
+ return -EFAULT;
+
+ break;
+
+ case CMD_PHY_WRITE:
+ if (copy_from_user(&phy_user_info, argp, sizeof(struct phydev_user_info)))
+ return -EFAULT;
+
+ ret = board_phy_write(phy_user_info.phy_index, phy_user_info.regnum, (u16)phy_user_info.regval);
+ if (ret < 0) {
+ return -EFAULT;
+ }
+
+ break;
+
+ case CMD_MDIO_LIST:
+ list_all_mdio_devices_info();
+ break;
+
+ case CMD_MDIO_READ:
+ if (copy_from_user(&mdio_user_info, argp, sizeof(struct mdio_dev_user_info)))
+ return -EFAULT;
+
+ ret = board_mdio_read(mdio_user_info.mdio_index, mdio_user_info.phyaddr, mdio_user_info.regnum);
+ if (ret < 0) {
+ return -EFAULT;
+ }
+
+ mdio_user_info.regval = (u32)ret;
+
+ if (copy_to_user(argp, &mdio_user_info, sizeof(struct mdio_dev_user_info)))
+ return -EFAULT;
+
+ break;
+
+ case CMD_MDIO_WRITE:
+ if (copy_from_user(&mdio_user_info, argp, sizeof(struct mdio_dev_user_info)))
+ return -EFAULT;
+
+ ret = board_mdio_write(mdio_user_info.mdio_index, mdio_user_info.phyaddr, mdio_user_info.regnum, (u16)mdio_user_info.regval);
+ if (ret < 0) {
+ return -EFAULT;
+ }
+
+ break;
+
+ default:
+ printk("unknown ioctl cmd\n");
+ break;
+ }
+
+ return 0;
+}
+
+static int dram_dev_open(struct inode *inode, struct file *file)
+{
+ file->private_data = NULL;
+ file->f_pos = 0;
+ return 0;
+
+}
+
+static int dram_dev_release(struct inode *inode, struct file *file)
+{
+ if (file->private_data) {
+ iounmap(file->private_data);
+ }
+ return 0;
+}
+
+static const struct file_operations dram_dev_fops = {
+ .owner = THIS_MODULE,
+ .llseek = dram_dev_llseek,
+ .read = dram_dev_read,
+ .write = dram_dev_write,
+ .unlocked_ioctl = dram_dev_ioctl,
+ .open = dram_dev_open,
+ .release = dram_dev_release,
+};
+
+static struct miscdevice dram_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "dram_test",
+ .fops = &dram_dev_fops,
+};
+
+static int __init dram_init(void)
+{
+ if (add_all_phydevs_to_list() != 0) {
+ printk(KERN_ERR "add all phydev to list fail\n");
+ delete_all_phydevs_from_list();
+ return -ENXIO;
+ }
+
+ if (init_class_mdio_bus() == 0) {
+ if (add_all_mdio_devices_to_list() == -EFAULT) {
+ printk(KERN_ERR "add all mdiodev to list fail\n");
+ delete_all_mdio_devices_from_list();
+ delete_all_phydevs_from_list();
+ return -ENXIO;
+ }
+ }
+
+ if (misc_register(&dram_dev) != 0) {
+ pr_notice("Register %s failed.\n", dram_dev.name);
+ delete_all_mdio_devices_from_list();
+ delete_all_phydevs_from_list();
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void __exit dram_exit(void)
+{
+ misc_deregister(&dram_dev);
+
+ delete_all_mdio_devices_from_list();
+ delete_all_phydevs_from_list();
+}
+
+module_init(dram_init);
+module_exit(dram_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("support");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.h
new file mode 100644
index 000000000000..695fa336c4ff
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.h
@@ -0,0 +1,31 @@
+
+#ifndef _LINUX_DRAM_DRIVER_H
+#define _LINUX_DRAM_DRIVER_H
+
+#include
+#include
+
+#define mem_clear(data, val, size) memset((data), val, (size))
+
+struct phydev_user_info {
+ int phy_index;
+ u32 regnum;
+ u32 regval;
+};
+
+#define CMD_PHY_LIST _IOR('P', 0, struct phydev_user_info)
+#define CMD_PHY_READ _IOR('P', 1, struct phydev_user_info)
+#define CMD_PHY_WRITE _IOR('P', 2, struct phydev_user_info)
+
+struct mdio_dev_user_info {
+ int mdio_index;
+ int phyaddr;
+ u32 regnum;
+ u32 regval;
+};
+
+#define CMD_MDIO_LIST _IOR('M', 0, struct mdio_dev_user_info)
+#define CMD_MDIO_READ _IOR('M', 1, struct mdio_dev_user_info)
+#define CMD_MDIO_WRITE _IOR('M', 2, struct mdio_dev_user_info)
+
+#endif
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/Makefile
new file mode 100644
index 000000000000..02d659d6c8b2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/Makefile
@@ -0,0 +1,37 @@
+PWD = $(shell pwd)
+
+EXTRA_CFLAGS:= -I$(M)/include
+EXTRA_CFLAGS+= -Wall
+#ifdef ENABLE_GCOV
+#ifeq ($(ENABLE_GCOV), y)
+#EXTRA_CFLAGS+= -fprofile-arcs -ftest-coverage -lgcov
+#endif
+#endif # ENABLE_GCOV
+
+obj-m := wb_lm75.o
+obj-m += wb_tmp401.o
+obj-m += wb_i2c_mux_pca9641.o
+obj-m += wb_i2c_mux_pca954x.o
+obj-m += wb_i2c_i801.o
+obj-m += wb_i2c_algo_bit.o
+obj-m += wb_i2c_gpio.o
+obj-m += wb_i2c_gpio_device.o
+obj-m += wb_at24.o
+obj-m += wb_pmbus_core.o
+obj-m += wb_csu550.o
+obj-m += wb_ina3221.o
+obj-m += wb_isl68137.o
+obj-m += wb_tps53622.o
+obj-m += wb_ucd9000.o
+obj-m += wb_xdpe12284.o
+obj-m += wb_xdpe132g5c_pmbus.o
+obj-m += wb_i2c_ismt.o
+
+all:
+ $(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules
+ @if [ ! -d $(module_out_put_dir) ]; then mkdir -p $(module_out_put_dir) ;fi
+ cp -p $(PWD)/*.ko $(module_out_put_dir)
+clean:
+ rm -f $(PWD)/*.o $(PWD)/*.ko $(PWD)/*.mod.c $(PWD)/.*.cmd $(PWD)/*.mod
+ rm -f $(PWD)/Module.markers $(PWD)/Module.symvers $(PWD)/modules.order
+ rm -rf $(PWD)/.tmp_versions
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_at24.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_at24.c
new file mode 100644
index 000000000000..5ec39c9d7dcb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_at24.c
@@ -0,0 +1,861 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * at24.c - handle most I2C EEPROMs
+ *
+ * Copyright (C) 2005-2007 David Brownell
+ * Copyright (C) 2008 Wolfram Sang, Pengutronix
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* Address pointer is 16 bit. */
+#define AT24_FLAG_ADDR16 BIT(7)
+/* sysfs-entry will be read-only. */
+#define AT24_FLAG_READONLY BIT(6)
+/* sysfs-entry will be world-readable. */
+#define AT24_FLAG_IRUGO BIT(5)
+/* Take always 8 addresses (24c00). */
+#define AT24_FLAG_TAKE8ADDR BIT(4)
+/* Factory-programmed serial number. */
+#define AT24_FLAG_SERIAL BIT(3)
+/* Factory-programmed mac address. */
+#define AT24_FLAG_MAC BIT(2)
+/* Does not auto-rollover reads to the next slave address. */
+#define AT24_FLAG_NO_RDROL BIT(1)
+
+/*
+ * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
+ * Differences between different vendor product lines (like Atmel AT24C or
+ * MicroChip 24LC, etc) won't much matter for typical read/write access.
+ * There are also I2C RAM chips, likewise interchangeable. One example
+ * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes).
+ *
+ * However, misconfiguration can lose data. "Set 16-bit memory address"
+ * to a part with 8-bit addressing will overwrite data. Writing with too
+ * big a page size also loses data. And it's not safe to assume that the
+ * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC
+ * uses 0x51, for just one example.
+ *
+ * Accordingly, explicit board-specific configuration data should be used
+ * in almost all cases. (One partial exception is an SMBus used to access
+ * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.)
+ *
+ * So this driver uses "new style" I2C driver binding, expecting to be
+ * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or
+ * similar kernel-resident tables; or, configuration data coming from
+ * a bootloader.
+ *
+ * Other than binding model, current differences from "eeprom" driver are
+ * that this one handles write access and isn't restricted to 24c02 devices.
+ * It also handles larger devices (32 kbit and up) with two-byte addresses,
+ * which won't work on pure SMBus systems.
+ */
+
+struct at24_client {
+ struct i2c_client *client;
+ struct regmap *regmap;
+};
+
+struct at24_data {
+ /*
+ * Lock protects against activities from other Linux tasks,
+ * but not from changes by other I2C masters.
+ */
+ struct mutex lock;
+
+ unsigned int write_max;
+ unsigned int num_addresses;
+ unsigned int offset_adj;
+
+ u32 byte_len;
+ u16 page_size;
+ u8 flags;
+
+ struct nvmem_device *nvmem;
+ struct regulator *vcc_reg;
+ void (*read_post)(unsigned int off, char *buf, size_t count);
+
+ /*
+ * Some chips tie up multiple I2C addresses; dummy devices reserve
+ * them for us, and we'll use them with SMBus calls.
+ */
+ struct at24_client client[];
+};
+
+/*
+ * This parameter is to help this driver avoid blocking other drivers out
+ * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C
+ * clock, one 256 byte read takes about 1/43 second which is excessive;
+ * but the 1/170 second it takes at 400 kHz may be quite reasonable; and
+ * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible.
+ *
+ * This value is forced to be a power of two so that writes align on pages.
+ */
+static unsigned int at24_io_limit = 128;
+module_param_named(io_limit, at24_io_limit, uint, 0);
+MODULE_PARM_DESC(at24_io_limit, "Maximum bytes per I/O (default 128)");
+
+/*
+ * Specs often allow 5 msec for a page write, sometimes 20 msec;
+ * it's important to recover from write timeouts.
+ */
+static unsigned int at24_write_timeout = 25;
+module_param_named(write_timeout, at24_write_timeout, uint, 0);
+MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)");
+
+struct at24_chip_data {
+ u32 byte_len;
+ u8 flags;
+ void (*read_post)(unsigned int off, char *buf, size_t count);
+};
+
+#define AT24_CHIP_DATA(_name, _len, _flags) \
+ static const struct at24_chip_data _name = { \
+ .byte_len = _len, .flags = _flags, \
+ }
+
+#define AT24_CHIP_DATA_CB(_name, _len, _flags, _read_post) \
+ static const struct at24_chip_data _name = { \
+ .byte_len = _len, .flags = _flags, \
+ .read_post = _read_post, \
+ }
+
+static void at24_read_post_vaio(unsigned int off, char *buf, size_t count)
+{
+ int i;
+
+ if (capable(CAP_SYS_ADMIN))
+ return;
+
+ /*
+ * Hide VAIO private settings to regular users:
+ * - BIOS passwords: bytes 0x00 to 0x0f
+ * - UUID: bytes 0x10 to 0x1f
+ * - Serial number: 0xc0 to 0xdf
+ */
+ for (i = 0; i < count; i++) {
+ if ((off + i <= 0x1f) ||
+ (off + i >= 0xc0 && off + i <= 0xdf))
+ buf[i] = 0;
+ }
+}
+
+/* needs 8 addresses as A0-A2 are ignored */
+AT24_CHIP_DATA(at24_data_24c00, 128 / 8, AT24_FLAG_TAKE8ADDR);
+/* old variants can't be handled with this generic entry! */
+AT24_CHIP_DATA(at24_data_24c01, 1024 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs01, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c02, 2048 / 8, AT24_FLAG_IRUGO);
+AT24_CHIP_DATA(at24_data_24cs02, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24mac402, 48 / 8,
+ AT24_FLAG_MAC | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24mac602, 64 / 8,
+ AT24_FLAG_MAC | AT24_FLAG_READONLY);
+/* spd is a 24c02 in memory DIMMs */
+AT24_CHIP_DATA(at24_data_spd, 2048 / 8,
+ AT24_FLAG_READONLY | AT24_FLAG_IRUGO);
+/* 24c02_vaio is a 24c02 on some Sony laptops */
+AT24_CHIP_DATA_CB(at24_data_24c02_vaio, 2048 / 8,
+ AT24_FLAG_READONLY | AT24_FLAG_IRUGO,
+ at24_read_post_vaio);
+AT24_CHIP_DATA(at24_data_24c04, 4096 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs04, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+/* 24rf08 quirk is handled at i2c-core */
+AT24_CHIP_DATA(at24_data_24c08, 8192 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs08, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c16, 16384 / 8, 0);
+AT24_CHIP_DATA(at24_data_24cs16, 16,
+ AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c32, 32768 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24cs32, 16,
+ AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c64, 65536 / 8, AT24_FLAG_ADDR16 | AT24_FLAG_IRUGO);
+AT24_CHIP_DATA(at24_data_24cs64, 16,
+ AT24_FLAG_ADDR16 | AT24_FLAG_SERIAL | AT24_FLAG_READONLY);
+AT24_CHIP_DATA(at24_data_24c128, 131072 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c256, 262144 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c512, 524288 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c1024, 1048576 / 8, AT24_FLAG_ADDR16);
+AT24_CHIP_DATA(at24_data_24c2048, 2097152 / 8, AT24_FLAG_ADDR16);
+/* identical to 24c08 ? */
+AT24_CHIP_DATA(at24_data_INT3499, 8192 / 8, 0);
+
+static const struct i2c_device_id at24_ids[] = {
+ { "wb_24c00", (kernel_ulong_t)&at24_data_24c00 },
+ { "wb_24c01", (kernel_ulong_t)&at24_data_24c01 },
+ { "wb_24cs01", (kernel_ulong_t)&at24_data_24cs01 },
+ { "wb_24c02", (kernel_ulong_t)&at24_data_24c02 },
+ { "wb_24cs02", (kernel_ulong_t)&at24_data_24cs02 },
+ { "wb_24mac402", (kernel_ulong_t)&at24_data_24mac402 },
+ { "wb_24mac602", (kernel_ulong_t)&at24_data_24mac602 },
+ { "wb_spd", (kernel_ulong_t)&at24_data_spd },
+ { "wb_24c02-vaio", (kernel_ulong_t)&at24_data_24c02_vaio },
+ { "wb_24c04", (kernel_ulong_t)&at24_data_24c04 },
+ { "wb_24cs04", (kernel_ulong_t)&at24_data_24cs04 },
+ { "wb_24c08", (kernel_ulong_t)&at24_data_24c08 },
+ { "wb_24cs08", (kernel_ulong_t)&at24_data_24cs08 },
+ { "wb_24c16", (kernel_ulong_t)&at24_data_24c16 },
+ { "wb_24cs16", (kernel_ulong_t)&at24_data_24cs16 },
+ { "wb_24c32", (kernel_ulong_t)&at24_data_24c32 },
+ { "wb_24cs32", (kernel_ulong_t)&at24_data_24cs32 },
+ { "wb_24c64", (kernel_ulong_t)&at24_data_24c64 },
+ { "wb_24cs64", (kernel_ulong_t)&at24_data_24cs64 },
+ { "wb_24c128", (kernel_ulong_t)&at24_data_24c128 },
+ { "wb_24c256", (kernel_ulong_t)&at24_data_24c256 },
+ { "wb_24c512", (kernel_ulong_t)&at24_data_24c512 },
+ { "wb_24c1024", (kernel_ulong_t)&at24_data_24c1024 },
+ { "wb_24c2048", (kernel_ulong_t)&at24_data_24c2048 },
+ { "wb_at24", 0 },
+ { /* END OF LIST */ }
+};
+MODULE_DEVICE_TABLE(i2c, at24_ids);
+
+static const struct of_device_id at24_of_match[] = {
+ { .compatible = "atmel,24c00", .data = &at24_data_24c00 },
+ { .compatible = "atmel,24c01", .data = &at24_data_24c01 },
+ { .compatible = "atmel,24cs01", .data = &at24_data_24cs01 },
+ { .compatible = "atmel,24c02", .data = &at24_data_24c02 },
+ { .compatible = "atmel,24cs02", .data = &at24_data_24cs02 },
+ { .compatible = "atmel,24mac402", .data = &at24_data_24mac402 },
+ { .compatible = "atmel,24mac602", .data = &at24_data_24mac602 },
+ { .compatible = "atmel,spd", .data = &at24_data_spd },
+ { .compatible = "atmel,24c04", .data = &at24_data_24c04 },
+ { .compatible = "atmel,24cs04", .data = &at24_data_24cs04 },
+ { .compatible = "atmel,24c08", .data = &at24_data_24c08 },
+ { .compatible = "atmel,24cs08", .data = &at24_data_24cs08 },
+ { .compatible = "atmel,24c16", .data = &at24_data_24c16 },
+ { .compatible = "atmel,24cs16", .data = &at24_data_24cs16 },
+ { .compatible = "atmel,24c32", .data = &at24_data_24c32 },
+ { .compatible = "atmel,24cs32", .data = &at24_data_24cs32 },
+ { .compatible = "atmel,24c64", .data = &at24_data_24c64 },
+ { .compatible = "atmel,24cs64", .data = &at24_data_24cs64 },
+ { .compatible = "atmel,24c128", .data = &at24_data_24c128 },
+ { .compatible = "atmel,24c256", .data = &at24_data_24c256 },
+ { .compatible = "atmel,24c512", .data = &at24_data_24c512 },
+ { .compatible = "atmel,24c1024", .data = &at24_data_24c1024 },
+ { .compatible = "atmel,24c2048", .data = &at24_data_24c2048 },
+ { /* END OF LIST */ },
+};
+MODULE_DEVICE_TABLE(of, at24_of_match);
+
+static const struct acpi_device_id __maybe_unused at24_acpi_ids[] = {
+ { "INT3499", (kernel_ulong_t)&at24_data_INT3499 },
+ { "TPF0001", (kernel_ulong_t)&at24_data_24c1024 },
+ { /* END OF LIST */ }
+};
+MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
+
+/*
+ * This routine supports chips which consume multiple I2C addresses. It
+ * computes the addressing information to be used for a given r/w request.
+ * Assumes that sanity checks for offset happened at sysfs-layer.
+ *
+ * Slave address and byte offset derive from the offset. Always
+ * set the byte address; on a multi-master board, another master
+ * may have changed the chip's "current" address pointer.
+ */
+static struct at24_client *at24_translate_offset(struct at24_data *at24,
+ unsigned int *offset)
+{
+ unsigned int i;
+
+ if (at24->flags & AT24_FLAG_ADDR16) {
+ i = *offset >> 16;
+ *offset &= 0xffff;
+ } else {
+ i = *offset >> 8;
+ *offset &= 0xff;
+ }
+
+ return &at24->client[i];
+}
+
+static struct device *at24_base_client_dev(struct at24_data *at24)
+{
+ return &at24->client[0].client->dev;
+}
+
+static size_t at24_adjust_read_count(struct at24_data *at24,
+ unsigned int offset, size_t count)
+{
+ unsigned int bits;
+ size_t remainder;
+
+ /*
+ * In case of multi-address chips that don't rollover reads to
+ * the next slave address: truncate the count to the slave boundary,
+ * so that the read never straddles slaves.
+ */
+ if (at24->flags & AT24_FLAG_NO_RDROL) {
+ bits = (at24->flags & AT24_FLAG_ADDR16) ? 16 : 8;
+ remainder = BIT(bits) - offset;
+ if (count > remainder)
+ count = remainder;
+ }
+
+ if (count > at24_io_limit)
+ count = at24_io_limit;
+
+ return count;
+}
+
+static ssize_t at24_regmap_read(struct at24_data *at24, char *buf,
+ unsigned int offset, size_t count)
+{
+ unsigned long timeout, read_time;
+ struct at24_client *at24_client;
+ struct i2c_client *client;
+ struct regmap *regmap;
+ int ret;
+
+ at24_client = at24_translate_offset(at24, &offset);
+ regmap = at24_client->regmap;
+ client = at24_client->client;
+ count = at24_adjust_read_count(at24, offset, count);
+
+ /* adjust offset for mac and serial read ops */
+ offset += at24->offset_adj;
+
+ timeout = jiffies + msecs_to_jiffies(at24_write_timeout);
+ do {
+ /*
+ * The timestamp shall be taken before the actual operation
+ * to avoid a premature timeout in case of high CPU load.
+ */
+ read_time = jiffies;
+
+ ret = regmap_bulk_read(regmap, offset, buf, count);
+ dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n",
+ count, offset, ret, jiffies);
+ if (!ret)
+ return count;
+
+ usleep_range(1000, 1500);
+ } while (time_before(read_time, timeout));
+
+ return -ETIMEDOUT;
+}
+
+/*
+ * Note that if the hardware write-protect pin is pulled high, the whole
+ * chip is normally write protected. But there are plenty of product
+ * variants here, including OTP fuses and partial chip protect.
+ *
+ * We only use page mode writes; the alternative is sloooow. These routines
+ * write at most one page.
+ */
+
+static size_t at24_adjust_write_count(struct at24_data *at24,
+ unsigned int offset, size_t count)
+{
+ unsigned int next_page;
+
+ /* write_max is at most a page */
+ if (count > at24->write_max)
+ count = at24->write_max;
+
+ /* Never roll over backwards, to the start of this page */
+ next_page = roundup(offset + 1, at24->page_size);
+ if (offset + count > next_page)
+ count = next_page - offset;
+
+ return count;
+}
+
+static ssize_t at24_regmap_write(struct at24_data *at24, const char *buf,
+ unsigned int offset, size_t count)
+{
+ unsigned long timeout, write_time;
+ struct at24_client *at24_client;
+ struct i2c_client *client;
+ struct regmap *regmap;
+ int ret;
+
+ at24_client = at24_translate_offset(at24, &offset);
+ regmap = at24_client->regmap;
+ client = at24_client->client;
+ count = at24_adjust_write_count(at24, offset, count);
+ timeout = jiffies + msecs_to_jiffies(at24_write_timeout);
+
+ do {
+ /*
+ * The timestamp shall be taken before the actual operation
+ * to avoid a premature timeout in case of high CPU load.
+ */
+ write_time = jiffies;
+
+ ret = regmap_bulk_write(regmap, offset, buf, count);
+ dev_dbg(&client->dev, "write %zu@%d --> %d (%ld)\n",
+ count, offset, ret, jiffies);
+ if (!ret)
+ return count;
+
+ usleep_range(1000, 1500);
+ } while (time_before(write_time, timeout));
+
+ return -ETIMEDOUT;
+}
+
+static int at24_read(void *priv, unsigned int off, void *val, size_t count)
+{
+ struct at24_data *at24;
+ struct device *dev;
+ char *buf = val;
+ int i, ret;
+
+ at24 = priv;
+ dev = at24_base_client_dev(at24);
+
+ if (unlikely(!count))
+ return count;
+
+ if (off + count > at24->byte_len)
+ return -EINVAL;
+
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ /*
+ * Read data from chip, protecting against concurrent updates
+ * from this host, but not from other I2C masters.
+ */
+ mutex_lock(&at24->lock);
+
+ for (i = 0; count; i += ret, count -= ret) {
+ ret = at24_regmap_read(at24, buf + i, off + i, count);
+ if (ret < 0) {
+ mutex_unlock(&at24->lock);
+ pm_runtime_put(dev);
+ return ret;
+ }
+ }
+
+ mutex_unlock(&at24->lock);
+
+ pm_runtime_put(dev);
+
+ if (unlikely(at24->read_post))
+ at24->read_post(off, buf, i);
+
+ return 0;
+}
+
+static int at24_write(void *priv, unsigned int off, void *val, size_t count)
+{
+ struct at24_data *at24;
+ struct device *dev;
+ char *buf = val;
+ int ret;
+
+ at24 = priv;
+ dev = at24_base_client_dev(at24);
+
+ if (unlikely(!count))
+ return -EINVAL;
+
+ if (off + count > at24->byte_len)
+ return -EINVAL;
+
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(dev);
+ return ret;
+ }
+
+ /*
+ * Write data to chip, protecting against concurrent updates
+ * from this host, but not from other I2C masters.
+ */
+ mutex_lock(&at24->lock);
+
+ while (count) {
+ ret = at24_regmap_write(at24, buf, off, count);
+ if (ret < 0) {
+ mutex_unlock(&at24->lock);
+ pm_runtime_put(dev);
+ return ret;
+ }
+ buf += ret;
+ off += ret;
+ count -= ret;
+ }
+
+ mutex_unlock(&at24->lock);
+
+ pm_runtime_put(dev);
+
+ return 0;
+}
+
+static const struct at24_chip_data *at24_get_chip_data(struct device *dev)
+{
+ struct device_node *of_node = dev->of_node;
+ const struct at24_chip_data *cdata;
+ const struct i2c_device_id *id;
+
+ id = i2c_match_id(at24_ids, to_i2c_client(dev));
+
+ /*
+ * The I2C core allows OF nodes compatibles to match against the
+ * I2C device ID table as a fallback, so check not only if an OF
+ * node is present but also if it matches an OF device ID entry.
+ */
+ if (of_node && of_match_device(at24_of_match, dev))
+ cdata = of_device_get_match_data(dev);
+ else if (id)
+ cdata = (void *)id->driver_data;
+ else
+ cdata = acpi_device_get_match_data(dev);
+
+ if (!cdata)
+ return ERR_PTR(-ENODEV);
+
+ return cdata;
+}
+
+static int at24_make_dummy_client(struct at24_data *at24, unsigned int index,
+ struct regmap_config *regmap_config)
+{
+ struct i2c_client *base_client, *dummy_client;
+ struct regmap *regmap;
+ struct device *dev;
+
+ base_client = at24->client[0].client;
+ dev = &base_client->dev;
+
+ dummy_client = devm_i2c_new_dummy_device(dev, base_client->adapter,
+ base_client->addr + index);
+ if (IS_ERR(dummy_client))
+ return PTR_ERR(dummy_client);
+
+ regmap = devm_regmap_init_i2c(dummy_client, regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ at24->client[index].client = dummy_client;
+ at24->client[index].regmap = regmap;
+
+ return 0;
+}
+
+static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len)
+{
+ if (flags & AT24_FLAG_MAC) {
+ /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */
+ return 0xa0 - byte_len;
+ } else if (flags & AT24_FLAG_SERIAL && flags & AT24_FLAG_ADDR16) {
+ /*
+ * For 16 bit address pointers, the word address must contain
+ * a '10' sequence in bits 11 and 10 regardless of the
+ * intended position of the address pointer.
+ */
+ return 0x0800;
+ } else if (flags & AT24_FLAG_SERIAL) {
+ /*
+ * Otherwise the word address must begin with a '10' sequence,
+ * regardless of the intended address.
+ */
+ return 0x0080;
+ } else {
+ return 0;
+ }
+}
+
+static int at24_probe(struct i2c_client *client)
+{
+ struct regmap_config regmap_config = { };
+ struct nvmem_config nvmem_config = { };
+ u32 byte_len, page_size, flags, addrw;
+ const struct at24_chip_data *cdata;
+ struct device *dev = &client->dev;
+ bool i2c_fn_i2c, i2c_fn_block;
+ unsigned int i, num_addresses;
+ struct at24_data *at24;
+ struct regmap *regmap;
+ bool writable;
+ u8 test_byte;
+ int err;
+
+ i2c_fn_i2c = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
+ i2c_fn_block = i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK);
+
+ cdata = at24_get_chip_data(dev);
+ if (IS_ERR(cdata))
+ return PTR_ERR(cdata);
+
+ err = device_property_read_u32(dev, "pagesize", &page_size);
+ if (err)
+ /*
+ * This is slow, but we can't know all eeproms, so we better
+ * play safe. Specifying custom eeprom-types via device tree
+ * or properties is recommended anyhow.
+ */
+ page_size = 1;
+
+ flags = cdata->flags;
+ if (device_property_present(dev, "read-only"))
+ flags |= AT24_FLAG_READONLY;
+ if (device_property_present(dev, "no-read-rollover"))
+ flags |= AT24_FLAG_NO_RDROL;
+
+ err = device_property_read_u32(dev, "address-width", &addrw);
+ if (!err) {
+ switch (addrw) {
+ case 8:
+ if (flags & AT24_FLAG_ADDR16)
+ dev_warn(dev,
+ "Override address width to be 8, while default is 16\n");
+ flags &= ~AT24_FLAG_ADDR16;
+ break;
+ case 16:
+ flags |= AT24_FLAG_ADDR16;
+ break;
+ default:
+ dev_warn(dev, "Bad \"address-width\" property: %u\n",
+ addrw);
+ }
+ }
+
+ err = device_property_read_u32(dev, "size", &byte_len);
+ if (err)
+ byte_len = cdata->byte_len;
+
+ if (!i2c_fn_i2c && !i2c_fn_block)
+ page_size = 1;
+
+ if (!page_size) {
+ dev_err(dev, "page_size must not be 0!\n");
+ return -EINVAL;
+ }
+
+ if (!is_power_of_2(page_size))
+ dev_warn(dev, "page_size looks suspicious (no power of 2)!\n");
+
+ err = device_property_read_u32(dev, "num-addresses", &num_addresses);
+ if (err) {
+ if (flags & AT24_FLAG_TAKE8ADDR)
+ num_addresses = 8;
+ else
+ num_addresses = DIV_ROUND_UP(byte_len,
+ (flags & AT24_FLAG_ADDR16) ? 65536 : 256);
+ }
+
+ if ((flags & AT24_FLAG_SERIAL) && (flags & AT24_FLAG_MAC)) {
+ dev_err(dev,
+ "invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC.");
+ return -EINVAL;
+ }
+
+ regmap_config.val_bits = 8;
+ regmap_config.reg_bits = (flags & AT24_FLAG_ADDR16) ? 16 : 8;
+ regmap_config.disable_locking = true;
+
+ regmap = devm_regmap_init_i2c(client, ®map_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ at24 = devm_kzalloc(dev, struct_size(at24, client, num_addresses),
+ GFP_KERNEL);
+ if (!at24)
+ return -ENOMEM;
+
+ mutex_init(&at24->lock);
+ at24->byte_len = byte_len;
+ at24->page_size = page_size;
+ at24->flags = flags;
+ at24->read_post = cdata->read_post;
+ at24->num_addresses = num_addresses;
+ at24->offset_adj = at24_get_offset_adj(flags, byte_len);
+ at24->client[0].client = client;
+ at24->client[0].regmap = regmap;
+
+ at24->vcc_reg = devm_regulator_get(dev, "vcc");
+ if (IS_ERR(at24->vcc_reg))
+ return PTR_ERR(at24->vcc_reg);
+
+ writable = !(flags & AT24_FLAG_READONLY);
+ if (writable) {
+ at24->write_max = min_t(unsigned int,
+ page_size, at24_io_limit);
+ if (!i2c_fn_i2c && at24->write_max > I2C_SMBUS_BLOCK_MAX)
+ at24->write_max = I2C_SMBUS_BLOCK_MAX;
+ }
+
+ /* use dummy devices for multiple-address chips */
+ for (i = 1; i < num_addresses; i++) {
+ err = at24_make_dummy_client(at24, i, ®map_config);
+ if (err)
+ return err;
+ }
+
+ /*
+ * If the 'label' property is not present for the AT24 EEPROM,
+ * then nvmem_config.id is initialised to NVMEM_DEVID_AUTO,
+ * and this will append the 'devid' to the name of the NVMEM
+ * device. This is purely legacy and the AT24 driver has always
+ * defaulted to this. However, if the 'label' property is
+ * present then this means that the name is specified by the
+ * firmware and this name should be used verbatim and so it is
+ * not necessary to append the 'devid'.
+ */
+ if (device_property_present(dev, "label")) {
+ nvmem_config.id = NVMEM_DEVID_NONE;
+ err = device_property_read_string(dev, "label",
+ &nvmem_config.name);
+ if (err)
+ return err;
+ } else {
+ nvmem_config.id = NVMEM_DEVID_AUTO;
+ nvmem_config.name = dev_name(dev);
+ }
+
+ nvmem_config.type = NVMEM_TYPE_EEPROM;
+ nvmem_config.dev = dev;
+ nvmem_config.read_only = !writable;
+ nvmem_config.root_only = !(flags & AT24_FLAG_IRUGO);
+ nvmem_config.owner = THIS_MODULE;
+ nvmem_config.compat = true;
+ nvmem_config.base_dev = dev;
+ nvmem_config.reg_read = at24_read;
+ nvmem_config.reg_write = at24_write;
+ nvmem_config.priv = at24;
+ nvmem_config.stride = 1;
+ nvmem_config.word_size = 1;
+ nvmem_config.size = byte_len;
+
+ i2c_set_clientdata(client, at24);
+
+ err = regulator_enable(at24->vcc_reg);
+ if (err) {
+ dev_err(dev, "Failed to enable vcc regulator\n");
+ return err;
+ }
+
+ /* enable runtime pm */
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(at24->nvmem)) {
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev))
+ regulator_disable(at24->vcc_reg);
+ return PTR_ERR(at24->nvmem);
+ }
+
+ /*
+ * Perform a one-byte test read to verify that the
+ * chip is functional.
+ */
+ err = at24_read(at24, 0, &test_byte, 1);
+ if (err) {
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev))
+ regulator_disable(at24->vcc_reg);
+ return -ENODEV;
+ }
+
+ pm_runtime_idle(dev);
+
+ if (writable)
+ dev_info(dev, "%u byte %s EEPROM, writable, %u bytes/write\n",
+ byte_len, client->name, at24->write_max);
+ else
+ dev_info(dev, "%u byte %s EEPROM, read-only\n",
+ byte_len, client->name);
+
+ return 0;
+}
+
+static void at24_remove(struct i2c_client *client)
+{
+ struct at24_data *at24 = i2c_get_clientdata(client);
+
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev))
+ regulator_disable(at24->vcc_reg);
+ pm_runtime_set_suspended(&client->dev);
+
+ return;
+}
+
+static int __maybe_unused at24_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct at24_data *at24 = i2c_get_clientdata(client);
+
+ return regulator_disable(at24->vcc_reg);
+}
+
+static int __maybe_unused at24_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct at24_data *at24 = i2c_get_clientdata(client);
+
+ return regulator_enable(at24->vcc_reg);
+}
+
+static const struct dev_pm_ops at24_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(at24_suspend, at24_resume, NULL)
+};
+
+static struct i2c_driver at24_driver = {
+ .driver = {
+ .name = "wb_at24",
+ .pm = &at24_pm_ops,
+ .of_match_table = at24_of_match,
+ .acpi_match_table = ACPI_PTR(at24_acpi_ids),
+ },
+ .probe_new = at24_probe,
+ .remove = at24_remove,
+ .id_table = at24_ids,
+};
+
+static int __init at24_init(void)
+{
+ if (!at24_io_limit) {
+ pr_err("at24: at24_io_limit must not be 0!\n");
+ return -EINVAL;
+ }
+
+ at24_io_limit = rounddown_pow_of_two(at24_io_limit);
+ return i2c_add_driver(&at24_driver);
+}
+module_init(at24_init);
+
+static void __exit at24_exit(void)
+{
+ i2c_del_driver(&at24_driver);
+}
+module_exit(at24_exit);
+
+MODULE_DESCRIPTION("Driver for most I2C EEPROMs");
+MODULE_AUTHOR("support");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_csu550.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_csu550.c
new file mode 100644
index 000000000000..36d07f071a71
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_csu550.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Hardware monitoring driver for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 Ericsson AB.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "wb_pmbus.h"
+
+struct pmbus_device_info {
+ int pages;
+ u32 flags;
+};
+
+static const struct i2c_device_id pmbus_id[];
+
+/*
+ * Find sensor groups and status registers on each page.
+ */
+static void pmbus_find_sensor_groups(struct i2c_client *client,
+ struct pmbus_driver_info *info)
+{
+ int page;
+
+ /* Sensors detected on page 0 only */
+ if (wb_pmbus_check_word_register(client, 0, PMBUS_READ_VIN))
+ info->func[0] |= PMBUS_HAVE_VIN;
+ if (wb_pmbus_check_word_register(client, 0, PMBUS_READ_IIN))
+ info->func[0] |= PMBUS_HAVE_IIN;
+ if (wb_pmbus_check_word_register(client, 0, PMBUS_READ_PIN))
+ info->func[0] |= PMBUS_HAVE_PIN;
+ if (info->func[0]
+ && wb_pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
+ info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
+ if (wb_pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) &&
+ wb_pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
+ info->func[0] |= PMBUS_HAVE_FAN12;
+ if (wb_pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
+ info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
+ }
+ if (wb_pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) &&
+ wb_pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
+ info->func[0] |= PMBUS_HAVE_FAN34;
+ if (wb_pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
+ info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
+ }
+ if (wb_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1))
+ info->func[0] |= PMBUS_HAVE_TEMP;
+ if (wb_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2))
+ info->func[0] |= PMBUS_HAVE_TEMP2;
+ if (wb_pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3))
+ info->func[0] |= PMBUS_HAVE_TEMP3;
+ if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
+ | PMBUS_HAVE_TEMP3)
+ && wb_pmbus_check_byte_register(client, 0,
+ PMBUS_STATUS_TEMPERATURE))
+ info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
+
+ /* Sensors detected on all pages */
+ for (page = 0; page < info->pages; page++) {
+ if (wb_pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) {
+ info->func[page] |= PMBUS_HAVE_VOUT;
+ if (wb_pmbus_check_byte_register(client, page,
+ PMBUS_STATUS_VOUT))
+ info->func[page] |= PMBUS_HAVE_STATUS_VOUT;
+ }
+ if (wb_pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) {
+ info->func[page] |= PMBUS_HAVE_IOUT;
+ if (wb_pmbus_check_byte_register(client, 0,
+ PMBUS_STATUS_IOUT))
+ info->func[page] |= PMBUS_HAVE_STATUS_IOUT;
+ }
+ if (wb_pmbus_check_word_register(client, page, PMBUS_READ_POUT))
+ info->func[page] |= PMBUS_HAVE_POUT;
+ }
+}
+
+/*
+ * Identify chip parameters.
+ */
+static int pmbus_identify(struct i2c_client *client,
+ struct pmbus_driver_info *info)
+{
+ int ret = 0;
+
+ if (!info->pages) {
+ /*
+ * Check if the PAGE command is supported. If it is,
+ * keep setting the page number until it fails or until the
+ * maximum number of pages has been reached. Assume that
+ * this is the number of pages supported by the chip.
+ */
+ if (wb_pmbus_check_byte_register(client, 0, PMBUS_PAGE)) {
+ int page;
+
+ for (page = 1; page < PMBUS_PAGES; page++) {
+ if (wb_pmbus_set_page(client, page, 0xff) < 0)
+ break;
+ }
+ wb_pmbus_set_page(client, 0, 0xff);
+ info->pages = page;
+ } else {
+ info->pages = 1;
+ }
+
+ wb_pmbus_clear_faults(client);
+ }
+
+ if (wb_pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) {
+ int vout_mode, i;
+
+ vout_mode = wb_pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+ if (vout_mode >= 0 && vout_mode != 0xff) {
+ switch (vout_mode >> 5) {
+ case 0:
+ break;
+ case 1:
+ info->format[PSC_VOLTAGE_OUT] = vid;
+ for (i = 0; i < info->pages; i++)
+ info->vrm_version[i] = vr11;
+ break;
+ case 2:
+ info->format[PSC_VOLTAGE_OUT] = direct;
+ break;
+ default:
+ ret = -ENODEV;
+ goto abort;
+ }
+ }
+ }
+
+ /*
+ * We should check if the COEFFICIENTS register is supported.
+ * If it is, and the chip is configured for direct mode, we can read
+ * the coefficients from the chip, one set per group of sensor
+ * registers.
+ *
+ * To do this, we will need access to a chip which actually supports the
+ * COEFFICIENTS command, since the command is too complex to implement
+ * without testing it. Until then, abort if a chip configured for direct
+ * mode was detected.
+ */
+ if (info->format[PSC_VOLTAGE_OUT] == direct) {
+ ret = -ENODEV;
+ goto abort;
+ }
+
+ /* Try to find sensor groups */
+ pmbus_find_sensor_groups(client, info);
+abort:
+ return ret;
+}
+
+static int pmbus_probe(struct i2c_client *client)
+{
+ struct pmbus_driver_info *info;
+ struct pmbus_platform_data *pdata = NULL;
+ struct device *dev = &client->dev;
+ struct pmbus_device_info *device_info;
+
+ info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ device_info = (struct pmbus_device_info *)i2c_match_id(pmbus_id, client)->driver_data;
+ if (device_info->flags & PMBUS_SKIP_STATUS_CHECK) {
+ pdata = devm_kzalloc(dev, sizeof(struct pmbus_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->flags = PMBUS_SKIP_STATUS_CHECK;
+ }
+
+ info->pages = device_info->pages;
+ info->identify = pmbus_identify;
+ dev->platform_data = pdata;
+
+ return wb_pmbus_do_probe(client, info);
+}
+
+static const struct pmbus_device_info pmbus_info_one = {
+ .pages = 1,
+ .flags = 0
+};
+
+static const struct pmbus_device_info pmbus_info_zero = {
+ .pages = 0,
+ .flags = 0
+};
+
+static const struct pmbus_device_info pmbus_info_one_skip = {
+ .pages = 1,
+ .flags = PMBUS_SKIP_STATUS_CHECK
+};
+
+static const struct pmbus_device_info pmbus_info_zero_skip = {
+ .pages = 0,
+ .flags = PMBUS_SKIP_STATUS_CHECK
+};
+/*
+ * Use driver_data to set the number of pages supported by the chip.
+ */
+static const struct i2c_device_id pmbus_id[] = {
+ {"wb_csu550", (kernel_ulong_t)&pmbus_info_zero_skip},
+ {"wb_csu800", (kernel_ulong_t)&pmbus_info_one_skip},
+ {"wb_fsp1200", (kernel_ulong_t)&pmbus_info_one_skip},
+ {"wb_dps550", (kernel_ulong_t)&pmbus_info_one_skip},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pmbus_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pmbus_driver = {
+ .driver = {
+ .name = "wb_pmbus",
+ },
+ .probe_new = pmbus_probe,
+ .remove = wb_pmbus_do_remove,
+ .id_table = pmbus_id,
+};
+
+module_i2c_driver(pmbus_driver);
+
+MODULE_AUTHOR("support");
+MODULE_DESCRIPTION("Generic PMBus driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_algo_bit.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_algo_bit.c
new file mode 100644
index 000000000000..c98ac7a1c5b6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_algo_bit.c
@@ -0,0 +1,725 @@
+/* -------------------------------------------------------------------------
+ * i2c-algo-bit.c i2c driver algorithms for bit-shift adapters
+ * -------------------------------------------------------------------------
+ * Copyright (C) 1995-2000 Simon G. Vogl
+
+ 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
+
+static int g_i2c_algo_bit_debug = 0;
+static int g_i2c_algo_bit_error = 0;
+
+module_param(g_i2c_algo_bit_debug, int, S_IRUGO | S_IWUSR);
+module_param(g_i2c_algo_bit_error, int, S_IRUGO | S_IWUSR);
+
+#define I2C_ALGO_BIT_DEBUG(fmt, args...) do { \
+ if (g_i2c_algo_bit_debug) { \
+ printk(KERN_INFO "[I2C_ALGO_BIT][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define I2C_ALGO_BIT_ERROR(fmt, args...) do { \
+ if (g_i2c_algo_bit_error) { \
+ printk(KERN_ERR "[I2C_ALGO_BIT][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+/* ----- global defines ----------------------------------------------- */
+
+#ifdef DEBUG
+#define bit_dbg(level, dev, format, args...) \
+ do { \
+ if (i2c_debug >= level) \
+ dev_dbg(dev, format, ##args); \
+ } while (0)
+#else
+#define bit_dbg(level, dev, format, args...) \
+ do {} while (0)
+#endif /* DEBUG */
+
+/* ----- global variables --------------------------------------------- */
+
+static int bit_test; /* see if the line-setting functions work */
+module_param(bit_test, int, S_IRUGO);
+MODULE_PARM_DESC(bit_test, "lines testing - 0 off; 1 report; 2 fail if stuck");
+
+#ifdef DEBUG
+static int i2c_debug = 1;
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(i2c_debug,
+ "debug level - 0 off; 1 normal; 2 verbose; 3 very verbose");
+#endif
+
+/* --- setting states on the bus with the right timing: --------------- */
+
+#define setsda(adap, val) adap->setsda(adap->data, val)
+#define setscl(adap, val) adap->setscl(adap->data, val)
+#define getsda(adap) adap->getsda(adap->data)
+#define getscl(adap) adap->getscl(adap->data)
+
+static inline void sdalo(struct i2c_algo_bit_data *adap)
+{
+ setsda(adap, 0);
+ udelay((adap->udelay + 1) / 2);
+}
+
+static inline void sdahi(struct i2c_algo_bit_data *adap)
+{
+ setsda(adap, 1);
+ udelay((adap->udelay + 1) / 2);
+}
+
+static inline void scllo(struct i2c_algo_bit_data *adap)
+{
+ setscl(adap, 0);
+ udelay(adap->udelay / 2);
+}
+
+/*
+ * Raise scl line, and do checking for delays. This is necessary for slower
+ * devices.
+ */
+static int sclhi(struct i2c_algo_bit_data *adap)
+{
+ unsigned long start;
+
+ setscl(adap, 1);
+
+ /* Not all adapters have scl sense line... */
+ if (!adap->getscl)
+ goto done;
+
+ start = jiffies;
+ while (!getscl(adap)) {
+ /* This hw knows how to read the clock line, so we wait
+ * until it actually gets high. This is safer as some
+ * chips may hold it low ("clock stretching") while they
+ * are processing data internally.
+ */
+ if (time_after(jiffies, start + adap->timeout)) {
+ /* Test one last time, as we may have been preempted
+ * between last check and timeout test.
+ */
+ if (getscl(adap))
+ break;
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
+#ifdef DEBUG
+ if (jiffies != start && i2c_debug >= 3)
+ pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
+ "high\n", jiffies - start);
+#endif
+
+done:
+ udelay(adap->udelay);
+ return 0;
+}
+
+/* --- other auxiliary functions -------------------------------------- */
+static void i2c_start(struct i2c_algo_bit_data *adap)
+{
+ /* assert: scl, sda are high */
+ setsda(adap, 0);
+ udelay(adap->udelay);
+ scllo(adap);
+}
+
+static void i2c_repstart(struct i2c_algo_bit_data *adap)
+{
+ /* assert: scl is low */
+ sdahi(adap);
+ sclhi(adap);
+ setsda(adap, 0);
+ udelay(adap->udelay);
+ scllo(adap);
+}
+
+static void i2c_stop(struct i2c_algo_bit_data *adap)
+{
+ /* assert: scl is low */
+ sdalo(adap);
+ sclhi(adap);
+ setsda(adap, 1);
+ udelay(adap->udelay);
+}
+
+/* send a byte without start cond., look for arbitration,
+ check ackn. from slave */
+/* returns:
+ * 1 if the device acknowledged
+ * 0 if the device did not ack
+ * -ETIMEDOUT if an error occurred (while raising the scl line)
+ */
+static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
+{
+ int i;
+ int sb;
+ int ack;
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+
+ /* assert: scl is low */
+ for (i = 7; i >= 0; i--) {
+ sb = (c >> i) & 1;
+ setsda(adap, sb);
+ udelay((adap->udelay + 1) / 2);
+ if (sclhi(adap) < 0) { /* timed out */
+ bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+ "timeout at bit #%d\n", (int)c, i);
+ return -ETIMEDOUT;
+ }
+ /* FIXME do arbitration here:
+ * if (sb && !getsda(adap)) -> ouch! Get out of here.
+ *
+ * Report a unique code, so higher level code can retry
+ * the whole (combined) message and *NOT* issue STOP.
+ */
+ scllo(adap);
+ }
+ sdahi(adap);
+ if (sclhi(adap) < 0) { /* timeout */
+ bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+ "timeout at ack\n", (int)c);
+ return -ETIMEDOUT;
+ }
+
+ /* read ack: SDA should be pulled down by slave, or it may
+ * NAK (usually to report problems with the data we wrote).
+ */
+ ack = !getsda(adap); /* ack: sda is pulled low -> success */
+ bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
+ ack ? "A" : "NA");
+
+ scllo(adap);
+ return ack;
+ /* assert: scl is low (sda undef) */
+}
+
+static int i2c_inb(struct i2c_adapter *i2c_adap)
+{
+ /* read byte via i2c port, without start/stop sequence */
+ /* acknowledge is sent in i2c_read. */
+ int i;
+ unsigned char indata = 0;
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+
+ /* assert: scl is low */
+ sdahi(adap);
+ for (i = 0; i < 8; i++) {
+ if (sclhi(adap) < 0) { /* timeout */
+ bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
+ "#%d\n", 7 - i);
+ return -ETIMEDOUT;
+ }
+ indata *= 2;
+ if (getsda(adap))
+ indata |= 0x01;
+ setscl(adap, 0);
+ udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
+ }
+ /* assert: scl is low */
+ return indata;
+}
+
+/*
+ * Sanity check for the adapter hardware - check the reaction of
+ * the bus lines only if it seems to be idle.
+ */
+static int test_bus(struct i2c_adapter *i2c_adap)
+{
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+ const char *name = i2c_adap->name;
+ int scl, sda, ret;
+
+ if (adap->pre_xfer) {
+ ret = adap->pre_xfer(i2c_adap);
+ if (ret < 0)
+ return -ENODEV;
+ }
+
+ if (adap->getscl == NULL)
+ pr_info("%s: Testing SDA only, SCL is not readable\n", name);
+
+ sda = getsda(adap);
+ scl = (adap->getscl == NULL) ? 1 : getscl(adap);
+ if (!scl || !sda) {
+ printk(KERN_WARNING
+ "%s: bus seems to be busy (scl=%d, sda=%d)\n",
+ name, scl, sda);
+ goto bailout;
+ }
+
+ sdalo(adap);
+ sda = getsda(adap);
+ scl = (adap->getscl == NULL) ? 1 : getscl(adap);
+ if (sda) {
+ printk(KERN_WARNING "%s: SDA stuck high!\n", name);
+ goto bailout;
+ }
+ if (!scl) {
+ printk(KERN_WARNING "%s: SCL unexpected low "
+ "while pulling SDA low!\n", name);
+ goto bailout;
+ }
+
+ sdahi(adap);
+ sda = getsda(adap);
+ scl = (adap->getscl == NULL) ? 1 : getscl(adap);
+ if (!sda) {
+ printk(KERN_WARNING "%s: SDA stuck low!\n", name);
+ goto bailout;
+ }
+ if (!scl) {
+ printk(KERN_WARNING "%s: SCL unexpected low "
+ "while pulling SDA high!\n", name);
+ goto bailout;
+ }
+
+ scllo(adap);
+ sda = getsda(adap);
+ scl = (adap->getscl == NULL) ? 0 : getscl(adap);
+ if (scl) {
+ printk(KERN_WARNING "%s: SCL stuck high!\n", name);
+ goto bailout;
+ }
+ if (!sda) {
+ printk(KERN_WARNING "%s: SDA unexpected low "
+ "while pulling SCL low!\n", name);
+ goto bailout;
+ }
+
+ sclhi(adap);
+ sda = getsda(adap);
+ scl = (adap->getscl == NULL) ? 1 : getscl(adap);
+ if (!scl) {
+ printk(KERN_WARNING "%s: SCL stuck low!\n", name);
+ goto bailout;
+ }
+ if (!sda) {
+ printk(KERN_WARNING "%s: SDA unexpected low "
+ "while pulling SCL high!\n", name);
+ goto bailout;
+ }
+
+ if (adap->post_xfer)
+ adap->post_xfer(i2c_adap);
+
+ pr_info("%s: Test OK\n", name);
+ return 0;
+bailout:
+ sdahi(adap);
+ sclhi(adap);
+
+ if (adap->post_xfer)
+ adap->post_xfer(i2c_adap);
+
+ return -ENODEV;
+}
+
+/* ----- Utility functions
+ */
+
+/* try_address tries to contact a chip for a number of
+ * times before it gives up.
+ * return values:
+ * 1 chip answered
+ * 0 chip did not answer
+ * -x transmission error
+ */
+static int try_address(struct i2c_adapter *i2c_adap,
+ unsigned char addr, int retries)
+{
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+ int i, ret = 0;
+
+ for (i = 0; i <= retries; i++) {
+ ret = i2c_outb(i2c_adap, addr);
+ if (ret == 1 || i == retries)
+ break;
+ bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
+ i2c_stop(adap);
+ udelay(adap->udelay);
+ yield();
+ bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
+ i2c_start(adap);
+ }
+ if (i && ret)
+ bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
+ "0x%02x: %s\n", i + 1,
+ addr & 1 ? "read from" : "write to", addr >> 1,
+ ret == 1 ? "success" : "failed, timeout?");
+ return ret;
+}
+
+static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+{
+ const unsigned char *temp = msg->buf;
+ int count = msg->len;
+ unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
+ int retval;
+ int wrcount = 0;
+
+ while (count > 0) {
+ retval = i2c_outb(i2c_adap, *temp);
+
+ /* OK/ACK; or ignored NAK */
+ if ((retval > 0) || (nak_ok && (retval == 0))) {
+ count--;
+ temp++;
+ wrcount++;
+
+ /* A slave NAKing the master means the slave didn't like
+ * something about the data it saw. For example, maybe
+ * the SMBus PEC was wrong.
+ */
+ } else if (retval == 0) {
+ dev_err(&i2c_adap->dev, "sendbytes: NAK bailout.\n");
+ return -EIO;
+
+ /* Timeout; or (someday) lost arbitration
+ *
+ * FIXME Lost ARB implies retrying the transaction from
+ * the first message, after the "winning" master issues
+ * its STOP. As a rule, upper layer code has no reason
+ * to know or care about this ... it is *NOT* an error.
+ */
+ } else {
+ dev_err(&i2c_adap->dev, "sendbytes: error %d\n",
+ retval);
+ return retval;
+ }
+ }
+ return wrcount;
+}
+
+static int acknak(struct i2c_adapter *i2c_adap, int is_ack)
+{
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+
+ /* assert: sda is high */
+ if (is_ack) /* send ack */
+ setsda(adap, 0);
+ udelay((adap->udelay + 1) / 2);
+ if (sclhi(adap) < 0) { /* timeout */
+ dev_err(&i2c_adap->dev, "readbytes: ack/nak timeout\n");
+ return -ETIMEDOUT;
+ }
+ scllo(adap);
+ return 0;
+}
+
+static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+{
+ int inval;
+ int rdcount = 0; /* counts bytes read */
+ unsigned char *temp = msg->buf;
+ int count = msg->len;
+ const unsigned flags = msg->flags;
+
+ while (count > 0) {
+ inval = i2c_inb(i2c_adap);
+ if (inval >= 0) {
+ *temp = inval;
+ rdcount++;
+ } else { /* read timed out */
+ break;
+ }
+
+ temp++;
+ count--;
+
+ /* Some SMBus transactions require that we receive the
+ transaction length as the first read byte. */
+ if (rdcount == 1 && (flags & I2C_M_RECV_LEN)) {
+ if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
+ if (!(flags & I2C_M_NO_RD_ACK))
+ acknak(i2c_adap, 0);
+ dev_err(&i2c_adap->dev, "readbytes: invalid "
+ "block length (%d)\n", inval);
+ return -EPROTO;
+ }
+ /* The original count value accounts for the extra
+ bytes, that is, either 1 for a regular transaction,
+ or 2 for a PEC transaction. */
+ count += inval;
+ msg->len += inval;
+ }
+
+ bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n",
+ inval,
+ (flags & I2C_M_NO_RD_ACK)
+ ? "(no ack/nak)"
+ : (count ? "A" : "NA"));
+
+ if (!(flags & I2C_M_NO_RD_ACK)) {
+ inval = acknak(i2c_adap, count);
+ if (inval < 0)
+ return inval;
+ }
+ }
+ return rdcount;
+}
+
+/* doAddress initiates the transfer by generating the start condition (in
+ * try_address) and transmits the address in the necessary format to handle
+ * reads, writes as well as 10bit-addresses.
+ * returns:
+ * 0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set
+ * -x an error occurred (like: -ENXIO if the device did not answer, or
+ * -ETIMEDOUT, for example if the lines are stuck...)
+ */
+static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+{
+ unsigned short flags = msg->flags;
+ unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+
+ unsigned char addr;
+ int ret, retries;
+
+ retries = nak_ok ? 0 : i2c_adap->retries;
+
+ if (flags & I2C_M_TEN) {
+ /* a ten bit address */
+ addr = 0xf0 | ((msg->addr >> 7) & 0x06);
+ bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
+ /* try extended address code...*/
+ ret = try_address(i2c_adap, addr, retries);
+ if ((ret != 1) && !nak_ok) {
+ dev_err(&i2c_adap->dev,
+ "died at extended address code\n");
+ return -ENXIO;
+ }
+ /* the remaining 8 bit address */
+ ret = i2c_outb(i2c_adap, msg->addr & 0xff);
+ if ((ret != 1) && !nak_ok) {
+ /* the chip did not ack / xmission error occurred */
+ dev_err(&i2c_adap->dev, "died at 2nd address code\n");
+ return -ENXIO;
+ }
+ if (flags & I2C_M_RD) {
+ bit_dbg(3, &i2c_adap->dev, "emitting repeated "
+ "start condition\n");
+ i2c_repstart(adap);
+ /* okay, now switch into reading mode */
+ addr |= 0x01;
+ ret = try_address(i2c_adap, addr, retries);
+ if ((ret != 1) && !nak_ok) {
+ dev_err(&i2c_adap->dev,
+ "died at repeated address code\n");
+ return -EIO;
+ }
+ }
+ } else { /* normal 7bit address */
+ addr = msg->addr << 1;
+ if (flags & I2C_M_RD)
+ addr |= 1;
+ if (flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+ ret = try_address(i2c_adap, addr, retries);
+ if ((ret != 1) && !nak_ok)
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static void bit_i2c_unblock(struct i2c_adapter *i2c_adap)
+{
+ int i;
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+
+ for (i = 0; i < 9; i++) {
+ setscl(adap, 0);
+ udelay(5);
+ setscl(adap, 1);
+ udelay(5);
+ }
+ setscl(adap, 0);
+ setsda(adap, 0);
+ udelay(5);
+ setscl(adap, 1);
+ udelay(5);
+ setsda(adap, 1);
+}
+
+static int check_bit_i2c_unblock(struct i2c_adapter *i2c_adap)
+{
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+ int sda, scl;
+
+ sda = getsda(adap);
+ scl = getscl(adap);
+ if ((sda == 0) && scl) {
+ I2C_ALGO_BIT_ERROR("SCL is high and SDA is low, send 9 clock to device.\n");
+ bit_i2c_unblock(i2c_adap);
+ }
+
+ sda = getsda(adap);
+ scl = getscl(adap);
+ if (sda && scl) {
+ I2C_ALGO_BIT_DEBUG("SCL and SDA are both high, i2c level check ok.\n");
+ return 0;
+ }
+ dev_warn(&i2c_adap->dev, "Check i2c level failed, SCL %s, SDA %s.\n", scl ? "high" : "low", sda ? "high" : "low");
+ return -EIO;
+}
+
+static int bit_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msgs[], int num)
+{
+ struct i2c_msg *pmsg;
+ struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+ int i, ret;
+ unsigned short nak_ok;
+
+ if (adap->pre_xfer) {
+ ret = adap->pre_xfer(i2c_adap);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (check_bit_i2c_unblock(i2c_adap) < 0) {
+ I2C_ALGO_BIT_ERROR("check i2c is block.\n");
+ return -EIO;
+ }
+
+ bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
+ i2c_start(adap);
+ for (i = 0; i < num; i++) {
+ pmsg = &msgs[i];
+ nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;
+ if (!(pmsg->flags & I2C_M_NOSTART)) {
+ if (i) {
+ bit_dbg(3, &i2c_adap->dev, "emitting "
+ "repeated start condition\n");
+ i2c_repstart(adap);
+ }
+ ret = bit_doAddress(i2c_adap, pmsg);
+ if ((ret != 0) && !nak_ok) {
+ bit_dbg(1, &i2c_adap->dev, "NAK from "
+ "device addr 0x%02x msg #%d\n",
+ msgs[i].addr, i);
+ goto bailout;
+ }
+ }
+ if (pmsg->flags & I2C_M_RD) {
+ /* read bytes into buffer*/
+ ret = readbytes(i2c_adap, pmsg);
+ if (ret >= 1)
+ bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",
+ ret, ret == 1 ? "" : "s");
+ if (ret < pmsg->len) {
+ if (ret >= 0)
+ ret = -EIO;
+ goto bailout;
+ }
+ } else {
+ /* write bytes from buffer */
+ ret = sendbytes(i2c_adap, pmsg);
+ if (ret >= 1)
+ bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",
+ ret, ret == 1 ? "" : "s");
+ if (ret < pmsg->len) {
+ if (ret >= 0)
+ ret = -EIO;
+ goto bailout;
+ }
+ }
+ }
+ ret = i;
+
+bailout:
+ bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
+ i2c_stop(adap);
+
+ if (adap->post_xfer)
+ adap->post_xfer(i2c_adap);
+ return ret;
+}
+
+static u32 bit_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
+}
+
+/* -----exported algorithm data: ------------------------------------- */
+
+const struct i2c_algorithm wb_i2c_bit_algo = {
+ .master_xfer = bit_xfer,
+ .functionality = bit_func,
+};
+EXPORT_SYMBOL(wb_i2c_bit_algo);
+
+static const struct i2c_adapter_quirks i2c_bit_quirk_no_clk_stretch = {
+ .flags = I2C_AQ_NO_CLK_STRETCH,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+static int __i2c_bit_add_bus(struct i2c_adapter *adap,
+ int (*add_adapter)(struct i2c_adapter *))
+{
+ struct i2c_algo_bit_data *bit_adap = adap->algo_data;
+ int ret;
+
+ if (bit_test) {
+ ret = test_bus(adap);
+ if (bit_test >= 2 && ret < 0)
+ return -ENODEV;
+ }
+
+ /* register new adapter to i2c module... */
+ adap->algo = &wb_i2c_bit_algo;
+ adap->retries = 3;
+ if (bit_adap->getscl == NULL)
+ adap->quirks = &i2c_bit_quirk_no_clk_stretch;
+
+ ret = add_adapter(adap);
+ if (ret < 0)
+ return ret;
+
+ /* Complain if SCL can't be read */
+ if (bit_adap->getscl == NULL) {
+ dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n");
+ dev_warn(&adap->dev, "Bus may be unreliable\n");
+ }
+ return 0;
+}
+
+int wb_i2c_bit_add_bus(struct i2c_adapter *adap)
+{
+ return __i2c_bit_add_bus(adap, i2c_add_adapter);
+}
+EXPORT_SYMBOL(wb_i2c_bit_add_bus);
+
+int wb_i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
+{
+ return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter);
+}
+EXPORT_SYMBOL(wb_i2c_bit_add_numbered_bus);
+
+MODULE_AUTHOR("support");
+MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_gpio.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_gpio.c
new file mode 100644
index 000000000000..0362e905fddb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_gpio.c
@@ -0,0 +1,431 @@
+/*
+ * Bitbanging I2C bus driver using the GPIO API
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern int wb_i2c_bit_add_numbered_bus(struct i2c_adapter *adap);
+
+struct i2c_gpio_private_data {
+ struct gpio_desc *sda;
+ struct gpio_desc *scl;
+ struct i2c_adapter adap;
+ struct i2c_algo_bit_data bit_data;
+ struct i2c_gpio_platform_data pdata;
+#ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR
+ struct dentry *debug_dir;
+#endif
+};
+
+/*
+ * Toggle SDA by changing the output value of the pin. This is only
+ * valid for pins configured as open drain (i.e. setting the value
+ * high effectively turns off the output driver.)
+ */
+static void i2c_gpio_setsda_val(void *data, int state)
+{
+ struct i2c_gpio_private_data *priv = data;
+
+ gpiod_set_value_cansleep(priv->sda, state);
+}
+
+/*
+ * Toggle SCL by changing the output value of the pin. This is used
+ * for pins that are configured as open drain and for output-only
+ * pins. The latter case will break the i2c protocol, but it will
+ * often work in practice.
+ */
+static void i2c_gpio_setscl_val(void *data, int state)
+{
+ struct i2c_gpio_private_data *priv = data;
+
+ gpiod_set_value_cansleep(priv->scl, state);
+}
+
+static int i2c_gpio_getsda(void *data)
+{
+ struct i2c_gpio_private_data *priv = data;
+
+ return gpiod_get_value_cansleep(priv->sda);
+}
+
+static int i2c_gpio_getscl(void *data)
+{
+ struct i2c_gpio_private_data *priv = data;
+
+ return gpiod_get_value_cansleep(priv->scl);
+}
+
+#ifdef CONFIG_I2C_GPIO_FAULT_INJECTOR
+static struct dentry *i2c_gpio_debug_dir;
+
+#define setsda(bd, val) ((bd)->setsda((bd)->data, val))
+#define setscl(bd, val) ((bd)->setscl((bd)->data, val))
+#define getsda(bd) ((bd)->getsda((bd)->data))
+#define getscl(bd) ((bd)->getscl((bd)->data))
+
+#define WIRE_ATTRIBUTE(wire) \
+static int fops_##wire##_get(void *data, u64 *val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ *val = get##wire(&priv->bit_data); \
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ return 0; \
+} \
+static int fops_##wire##_set(void *data, u64 val) \
+{ \
+ struct i2c_gpio_private_data *priv = data; \
+ \
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ set##wire(&priv->bit_data, val); \
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER); \
+ return 0; \
+} \
+DEFINE_DEBUGFS_ATTRIBUTE(fops_##wire, fops_##wire##_get, fops_##wire##_set, "%llu\n")
+
+WIRE_ATTRIBUTE(scl);
+WIRE_ATTRIBUTE(sda);
+
+static void i2c_gpio_incomplete_transfer(struct i2c_gpio_private_data *priv,
+ u32 pattern, u8 pattern_size)
+{
+ struct i2c_algo_bit_data *bit_data = &priv->bit_data;
+ int i;
+
+ i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
+
+ /* START condition */
+ setsda(bit_data, 0);
+ udelay(bit_data->udelay);
+
+ /* Send pattern, request ACK, don't send STOP */
+ for (i = pattern_size - 1; i >= 0; i--) {
+ setscl(bit_data, 0);
+ udelay(bit_data->udelay / 2);
+ setsda(bit_data, (pattern >> i) & 1);
+ udelay((bit_data->udelay + 1) / 2);
+ setscl(bit_data, 1);
+ udelay(bit_data->udelay);
+ }
+
+ i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
+}
+
+static int fops_incomplete_addr_phase_set(void *data, u64 addr)
+{
+ struct i2c_gpio_private_data *priv = data;
+ u32 pattern;
+
+ if (addr > 0x7f)
+ return -EINVAL;
+
+ /* ADDR (7 bit) + RD (1 bit) + Client ACK, keep SDA hi (1 bit) */
+ pattern = (addr << 2) | 3;
+
+ i2c_gpio_incomplete_transfer(priv, pattern, 9);
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_addr_phase, NULL, fops_incomplete_addr_phase_set, "%llu\n");
+
+static int fops_incomplete_write_byte_set(void *data, u64 addr)
+{
+ struct i2c_gpio_private_data *priv = data;
+ u32 pattern;
+
+ if (addr > 0x7f)
+ return -EINVAL;
+
+ /* ADDR (7 bit) + WR (1 bit) + Client ACK (1 bit) */
+ pattern = (addr << 2) | 1;
+ /* 0x00 (8 bit) + Client ACK, keep SDA hi (1 bit) */
+ pattern = (pattern << 9) | 1;
+
+ i2c_gpio_incomplete_transfer(priv, pattern, 18);
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_write_byte, NULL, fops_incomplete_write_byte_set, "%llu\n");
+
+static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
+{
+ struct i2c_gpio_private_data *priv = platform_get_drvdata(pdev);
+
+ /*
+ * If there will be a debugfs-dir per i2c adapter somewhen, put the
+ * 'fault-injector' dir there. Until then, we have a global dir with
+ * all adapters as subdirs.
+ */
+ if (!i2c_gpio_debug_dir) {
+ i2c_gpio_debug_dir = debugfs_create_dir("i2c-fault-injector", NULL);
+ if (!i2c_gpio_debug_dir)
+ return;
+ }
+
+ priv->debug_dir = debugfs_create_dir(pdev->name, i2c_gpio_debug_dir);
+ if (!priv->debug_dir)
+ return;
+
+ debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl);
+ debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda);
+ debugfs_create_file_unsafe("incomplete_address_phase", 0200, priv->debug_dir,
+ priv, &fops_incomplete_addr_phase);
+ debugfs_create_file_unsafe("incomplete_write_byte", 0200, priv->debug_dir,
+ priv, &fops_incomplete_write_byte);
+}
+
+static void i2c_gpio_fault_injector_exit(struct platform_device *pdev)
+{
+ struct i2c_gpio_private_data *priv = platform_get_drvdata(pdev);
+
+ debugfs_remove_recursive(priv->debug_dir);
+}
+#else
+static inline void i2c_gpio_fault_injector_init(struct platform_device *pdev) {}
+static inline void i2c_gpio_fault_injector_exit(struct platform_device *pdev) {}
+#endif /* CONFIG_I2C_GPIO_FAULT_INJECTOR*/
+
+static void of_i2c_gpio_get_props(struct device_node *np,
+ struct i2c_gpio_platform_data *pdata)
+{
+ u32 reg;
+
+ of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
+
+ if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®))
+ pdata->timeout = msecs_to_jiffies(reg);
+
+ pdata->sda_is_open_drain =
+ of_property_read_bool(np, "i2c-gpio,sda-open-drain");
+ pdata->scl_is_open_drain =
+ of_property_read_bool(np, "i2c-gpio,scl-open-drain");
+ pdata->scl_is_output_only =
+ of_property_read_bool(np, "i2c-gpio,scl-output-only");
+}
+
+static struct gpio_desc *i2c_gpio_get_desc(struct device *dev,
+ const char *con_id,
+ unsigned int index,
+ enum gpiod_flags gflags)
+{
+ struct gpio_desc *retdesc;
+ int ret;
+
+ retdesc = devm_gpiod_get(dev, con_id, gflags);
+ if (!IS_ERR(retdesc)) {
+ dev_dbg(dev, "got GPIO from name %s\n", con_id);
+ return retdesc;
+ }
+
+ retdesc = devm_gpiod_get_index(dev, NULL, index, gflags);
+ if (!IS_ERR(retdesc)) {
+ dev_dbg(dev, "got GPIO from index %u\n", index);
+ return retdesc;
+ }
+
+ ret = PTR_ERR(retdesc);
+
+ /* FIXME: hack in the old code, is this really necessary? */
+ if (ret == -EINVAL)
+ retdesc = ERR_PTR(-EPROBE_DEFER);
+
+ /* This happens if the GPIO driver is not yet probed, let's defer */
+ if (ret == -ENOENT)
+ retdesc = ERR_PTR(-EPROBE_DEFER);
+
+ if (PTR_ERR(retdesc) != -EPROBE_DEFER)
+ dev_err(dev, "error trying to get descriptor: %d\n", ret);
+
+ return retdesc;
+}
+
+static int i2c_gpio_probe(struct platform_device *pdev)
+{
+ struct i2c_gpio_private_data *priv;
+ struct i2c_gpio_platform_data *pdata;
+ struct i2c_algo_bit_data *bit_data;
+ struct i2c_adapter *adap;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ enum gpiod_flags gflags;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ adap = &priv->adap;
+ bit_data = &priv->bit_data;
+ pdata = &priv->pdata;
+
+ if (np) {
+ of_i2c_gpio_get_props(np, pdata);
+ } else {
+ /*
+ * If all platform data settings are zero it is OK
+ * to not provide any platform data from the board.
+ */
+ if (dev_get_platdata(dev))
+ memcpy(pdata, dev_get_platdata(dev), sizeof(*pdata));
+ }
+
+ /*
+ * First get the GPIO pins; if it fails, we'll defer the probe.
+ * If the SDA line is marked from platform data or device tree as
+ * "open drain" it means something outside of our control is making
+ * this line being handled as open drain, and we should just handle
+ * it as any other output. Else we enforce open drain as this is
+ * required for an I2C bus.
+ */
+ if (pdata->sda_is_open_drain)
+ gflags = GPIOD_OUT_HIGH;
+ else
+ gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
+ priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags);
+ if (IS_ERR(priv->sda))
+ return PTR_ERR(priv->sda);
+
+ /*
+ * If the SCL line is marked from platform data or device tree as
+ * "open drain" it means something outside of our control is making
+ * this line being handled as open drain, and we should just handle
+ * it as any other output. Else we enforce open drain as this is
+ * required for an I2C bus.
+ */
+ if (pdata->scl_is_open_drain)
+ gflags = GPIOD_OUT_HIGH;
+ else
+ gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
+ priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags);
+ if (IS_ERR(priv->scl))
+ return PTR_ERR(priv->scl);
+
+ if (gpiod_cansleep(priv->sda) || gpiod_cansleep(priv->scl))
+ dev_warn(dev, "Slow GPIO pins might wreak havoc into I2C/SMBus bus timing");
+
+ bit_data->setsda = i2c_gpio_setsda_val;
+ bit_data->setscl = i2c_gpio_setscl_val;
+
+ if (!pdata->scl_is_output_only)
+ bit_data->getscl = i2c_gpio_getscl;
+ bit_data->getsda = i2c_gpio_getsda;
+
+ if (pdata->udelay)
+ bit_data->udelay = pdata->udelay;
+ else if (pdata->scl_is_output_only)
+ bit_data->udelay = 50; /* 10 kHz */
+ else
+ bit_data->udelay = 5; /* 100 kHz */
+
+ if (pdata->timeout)
+ bit_data->timeout = pdata->timeout;
+ else
+ bit_data->timeout = HZ / 10; /* 100 ms */
+
+ bit_data->data = priv;
+
+ adap->owner = THIS_MODULE;
+ if (np)
+ strlcpy(adap->name, dev_name(dev), sizeof(adap->name));
+ else
+ snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
+
+ adap->algo_data = bit_data;
+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ adap->dev.parent = dev;
+ adap->dev.of_node = np;
+
+ adap->nr = pdev->id;
+ ret = wb_i2c_bit_add_numbered_bus(adap);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, priv);
+
+ /*
+ * FIXME: using global GPIO numbers is not helpful. If/when we
+ * get accessors to get the actual name of the GPIO line,
+ * from the descriptor, then provide that instead.
+ */
+ dev_info(dev, "using lines %u (SDA) and %u (SCL%s)\n",
+ desc_to_gpio(priv->sda), desc_to_gpio(priv->scl),
+ pdata->scl_is_output_only
+ ? ", no clock stretching" : "");
+
+ i2c_gpio_fault_injector_init(pdev);
+
+ return 0;
+}
+
+static int i2c_gpio_remove(struct platform_device *pdev)
+{
+ struct i2c_gpio_private_data *priv;
+ struct i2c_adapter *adap;
+
+ i2c_gpio_fault_injector_exit(pdev);
+
+ priv = platform_get_drvdata(pdev);
+ adap = &priv->adap;
+
+ i2c_del_adapter(adap);
+
+ return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id i2c_gpio_dt_ids[] = {
+ { .compatible = "wb-i2c-gpio", },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids);
+#endif
+
+static struct platform_driver i2c_gpio_driver = {
+ .driver = {
+ .name = "wb-i2c-gpio",
+ .of_match_table = of_match_ptr(i2c_gpio_dt_ids),
+ },
+ .probe = i2c_gpio_probe,
+ .remove = i2c_gpio_remove,
+};
+
+static int __init i2c_gpio_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&i2c_gpio_driver);
+ if (ret)
+ printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
+
+ return ret;
+}
+subsys_initcall(i2c_gpio_init);
+
+static void __exit i2c_gpio_exit(void)
+{
+ platform_driver_unregister(&i2c_gpio_driver);
+}
+module_exit(i2c_gpio_exit);
+
+MODULE_AUTHOR("support");
+MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:i2c-gpio");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_gpio_device.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_gpio_device.c
new file mode 100644
index 000000000000..1e1d815eedf1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_gpio_device.c
@@ -0,0 +1,133 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define I2C_GPIO_DEV_NAME_LEN (16)
+static char i2c_gpio_dev_name[I2C_GPIO_DEV_NAME_LEN] = {0};
+
+static int gpio_sda = 17;
+module_param(gpio_sda, int, S_IRUGO | S_IWUSR);
+
+static int gpio_scl = 1;
+module_param(gpio_scl, int, S_IRUGO | S_IWUSR);
+
+static int gpio_udelay = 2;
+module_param(gpio_udelay, int, S_IRUGO | S_IWUSR);
+
+static int bus_num = -1;
+module_param(bus_num, int, S_IRUGO | S_IWUSR);
+
+static char *gpio_chip_name = NULL;
+module_param(gpio_chip_name, charp, 0644);
+MODULE_PARM_DESC(str_var, "A string variable for GPIO controller");
+
+static int g_wb_i2c_gpio_device_debug = 0;
+static int g_wb_i2c_gpio_device_error = 0;
+
+module_param(g_wb_i2c_gpio_device_debug, int, S_IRUGO | S_IWUSR);
+module_param(g_wb_i2c_gpio_device_error, int, S_IRUGO | S_IWUSR);
+
+#define WB_I2C_GPIO_DEVICE_VERBOSE(fmt, args...) do { \
+ if (g_wb_i2c_gpio_device_debug) { \
+ printk(KERN_INFO "[WB_I2C_GPIO_DEVICE][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define WB_I2C_GPIO_DEVICE_ERROR(fmt, args...) do { \
+ if (g_wb_i2c_gpio_device_error) { \
+ printk(KERN_ERR "[WB_I2C_GPIO_DEVICE][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+/****************** i2c adapter with gpio ***********************/
+static struct i2c_gpio_platform_data i2c_pdata = {
+ .udelay = 2,
+ .scl_is_output_only = 0,
+ .sda_is_open_drain = 0,
+ .scl_is_open_drain = 0,
+};
+
+static void i2c_gpio_release(struct device *dev)
+{
+ return;
+}
+
+static struct platform_device wb_i2c_gpio_device = {
+ .name = "wb-i2c-gpio",
+ .id = -1,
+ .num_resources = 0,
+ .resource = NULL,
+ .dev = {
+ .platform_data = &i2c_pdata,
+ .release = i2c_gpio_release,
+ },
+};
+
+/*
+ * i2c
+ */
+static struct gpiod_lookup_table wb_i2c_gpio_table = {
+ .dev_id = "wb-i2c-gpio",
+ .table = {
+ GPIO_LOOKUP("wb_gpio_d1500", 17, "sda",
+ GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+ GPIO_LOOKUP("wb_gpio_d1500", 1, "scl",
+ GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+ { },
+ },
+};
+
+static int __init wb_i2c_gpio_device_init(void)
+{
+ int err;
+
+ WB_I2C_GPIO_DEVICE_VERBOSE("wb_i2c_gpio_device_init enter!\n");
+ wb_i2c_gpio_table.table[0].chip_hwnum = gpio_sda;
+ wb_i2c_gpio_table.table[1].chip_hwnum = gpio_scl;
+ i2c_pdata.udelay = gpio_udelay;
+
+ if (gpio_chip_name) {
+ wb_i2c_gpio_table.table[0].key = gpio_chip_name;
+ wb_i2c_gpio_table.table[1].key = gpio_chip_name;
+ }
+
+ if (bus_num >= 0) {
+ wb_i2c_gpio_device.id = bus_num;
+ snprintf(i2c_gpio_dev_name, I2C_GPIO_DEV_NAME_LEN, "wb-i2c-gpio.%d", bus_num);
+ wb_i2c_gpio_table.dev_id = i2c_gpio_dev_name;
+ }
+
+ gpiod_add_lookup_table(&wb_i2c_gpio_table);
+
+ err = platform_device_register(&wb_i2c_gpio_device);
+ if (err < 0) {
+ printk(KERN_ERR "register i2c gpio device fail(%d). \n", err);
+ gpiod_remove_lookup_table(&wb_i2c_gpio_table);
+ return -1;
+ }
+ return 0;
+}
+
+static void __exit wb_i2c_gpio_device_exit(void)
+{
+ WB_I2C_GPIO_DEVICE_VERBOSE("wb_i2c_gpio_device_exit enter!\n");
+ platform_device_unregister(&wb_i2c_gpio_device);
+ gpiod_remove_lookup_table(&wb_i2c_gpio_table);
+}
+
+module_init(wb_i2c_gpio_device_init);
+module_exit(wb_i2c_gpio_device_exit);
+MODULE_DESCRIPTION("I2C GPIO Devices");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("support");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_i801.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_i801.c
new file mode 100644
index 000000000000..a733c115487e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_i801.c
@@ -0,0 +1,2114 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ Copyright (c) 1998 - 2002 Frodo Looijaard ,
+ Philip Edelbrock , and Mark D. Studebaker
+
+ Copyright (C) 2007 - 2014 Jean Delvare
+ Copyright (C) 2010 Intel Corporation,
+ David Woodhouse
+
+*/
+
+/*
+ * Supports the following Intel I/O Controller Hubs (ICH):
+ *
+ * I/O Block I2C
+ * region SMBus Block proc. block
+ * Chip name PCI ID size PEC buffer call read
+ * ---------------------------------------------------------------------------
+ * 82801AA (ICH) 0x2413 16 no no no no
+ * 82801AB (ICH0) 0x2423 16 no no no no
+ * 82801BA (ICH2) 0x2443 16 no no no no
+ * 82801CA (ICH3) 0x2483 32 soft no no no
+ * 82801DB (ICH4) 0x24c3 32 hard yes no no
+ * 82801E (ICH5) 0x24d3 32 hard yes yes yes
+ * 6300ESB 0x25a4 32 hard yes yes yes
+ * 82801F (ICH6) 0x266a 32 hard yes yes yes
+ * 6310ESB/6320ESB 0x269b 32 hard yes yes yes
+ * 82801G (ICH7) 0x27da 32 hard yes yes yes
+ * 82801H (ICH8) 0x283e 32 hard yes yes yes
+ * 82801I (ICH9) 0x2930 32 hard yes yes yes
+ * EP80579 (Tolapai) 0x5032 32 hard yes yes yes
+ * ICH10 0x3a30 32 hard yes yes yes
+ * ICH10 0x3a60 32 hard yes yes yes
+ * 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes
+ * 6 Series (PCH) 0x1c22 32 hard yes yes yes
+ * Patsburg (PCH) 0x1d22 32 hard yes yes yes
+ * Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes
+ * Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes
+ * Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes
+ * DH89xxCC (PCH) 0x2330 32 hard yes yes yes
+ * Panther Point (PCH) 0x1e22 32 hard yes yes yes
+ * Lynx Point (PCH) 0x8c22 32 hard yes yes yes
+ * Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes
+ * Avoton (SOC) 0x1f3c 32 hard yes yes yes
+ * Wellsburg (PCH) 0x8d22 32 hard yes yes yes
+ * Wellsburg (PCH) MS 0x8d7d 32 hard yes yes yes
+ * Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes
+ * Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes
+ * Coleto Creek (PCH) 0x23b0 32 hard yes yes yes
+ * Wildcat Point (PCH) 0x8ca2 32 hard yes yes yes
+ * Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes
+ * BayTrail (SOC) 0x0f12 32 hard yes yes yes
+ * Braswell (SOC) 0x2292 32 hard yes yes yes
+ * Sunrise Point-H (PCH) 0xa123 32 hard yes yes yes
+ * Sunrise Point-LP (PCH) 0x9d23 32 hard yes yes yes
+ * DNV (SOC) 0x19df 32 hard yes yes yes
+ * Emmitsburg (PCH) 0x1bc9 32 hard yes yes yes
+ * Broxton (SOC) 0x5ad4 32 hard yes yes yes
+ * Lewisburg (PCH) 0xa1a3 32 hard yes yes yes
+ * Lewisburg Supersku (PCH) 0xa223 32 hard yes yes yes
+ * Kaby Lake PCH-H (PCH) 0xa2a3 32 hard yes yes yes
+ * Gemini Lake (SOC) 0x31d4 32 hard yes yes yes
+ * Cannon Lake-H (PCH) 0xa323 32 hard yes yes yes
+ * Cannon Lake-LP (PCH) 0x9da3 32 hard yes yes yes
+ * Cedar Fork (PCH) 0x18df 32 hard yes yes yes
+ * Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes
+ * Comet Lake (PCH) 0x02a3 32 hard yes yes yes
+ * Comet Lake-H (PCH) 0x06a3 32 hard yes yes yes
+ * Elkhart Lake (PCH) 0x4b23 32 hard yes yes yes
+ * Tiger Lake-LP (PCH) 0xa0a3 32 hard yes yes yes
+ * Tiger Lake-H (PCH) 0x43a3 32 hard yes yes yes
+ * Jasper Lake (SOC) 0x4da3 32 hard yes yes yes
+ * Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes
+ * Alder Lake-S (PCH) 0x7aa3 32 hard yes yes yes
+ *
+ * Features supported by this driver:
+ * Software PEC no
+ * Hardware PEC yes
+ * Block buffer yes
+ * Block process call transaction yes
+ * I2C block read transaction yes (doesn't use the block buffer)
+ * Slave mode no
+ * SMBus Host Notify yes
+ * Interrupt processing yes
+ *
+ * See the file Documentation/i2c/busses/i2c-i801.rst for details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
+#include
+#include
+#endif
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+/* I801 SMBus address offsets */
+#define SMBHSTSTS(p) (0 + (p)->smba)
+#define SMBHSTCNT(p) (2 + (p)->smba)
+#define SMBHSTCMD(p) (3 + (p)->smba)
+#define SMBHSTADD(p) (4 + (p)->smba)
+#define SMBHSTDAT0(p) (5 + (p)->smba)
+#define SMBHSTDAT1(p) (6 + (p)->smba)
+#define SMBBLKDAT(p) (7 + (p)->smba)
+#define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */
+#define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */
+#define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */
+#define SMBSLVSTS(p) (16 + (p)->smba) /* ICH3 and later */
+#define SMBSLVCMD(p) (17 + (p)->smba) /* ICH3 and later */
+#define SMBNTFDADD(p) (20 + (p)->smba) /* ICH3 and later */
+#define SMBPINCTL(p) (15 + (p)->smba) /* SMBus Pin Control Register */
+
+/* PCI Address Constants */
+#define SMBBAR 4
+#define SMBPCICTL 0x004
+#define SMBPCISTS 0x006
+#define SMBHSTCFG 0x040
+#define TCOBASE 0x050
+#define TCOCTL 0x054
+
+#define SBREG_BAR 0x10
+#define SBREG_SMBCTRL 0xc6000c
+#define SBREG_SMBCTRL_DNV 0xcf000c
+
+/* Host status bits for SMBPCISTS */
+#define SMBPCISTS_INTS BIT(3)
+
+/* Control bits for SMBPCICTL */
+#define SMBPCICTL_INTDIS BIT(10)
+
+/* Host configuration bits for SMBHSTCFG */
+#define SMBHSTCFG_HST_EN BIT(0)
+#define SMBHSTCFG_SMB_SMI_EN BIT(1)
+#define SMBHSTCFG_I2C_EN BIT(2)
+#define SMBHSTCFG_SSRESET BIT(3)
+#define SSRESET_SLEEP_TIME 1 /* 1us */
+#define SSRESET_RETRY_TIME (1000 / SSRESET_SLEEP_TIME)
+
+/* Pin status for SMBPINCTL */
+#define SMBPINCTL_CLK_STS 1 /* bit0 SMBCLK_CUR_STS*/
+#define SMBPINCTL_SDA_STS 2 /* bit1 SMBDATA_CUR_STS*/
+#define SMBPINCTL_CLK_CTL 4 /* bit2 SMBCLK_CTL */
+
+#define SMBHSTCFG_SPD_WD BIT(4)
+
+/* TCO configuration bits for TCOCTL */
+#define TCOCTL_EN BIT(8)
+
+/* Auxiliary status register bits, ICH4+ only */
+#define SMBAUXSTS_CRCE BIT(0)
+#define SMBAUXSTS_STCO BIT(1)
+
+/* Auxiliary control register bits, ICH4+ only */
+#define SMBAUXCTL_CRC BIT(0)
+#define SMBAUXCTL_E32B BIT(1)
+
+/* Other settings */
+#define MAX_RETRIES 400
+
+/* I801 command constants */
+#define I801_QUICK 0x00
+#define I801_BYTE 0x04
+#define I801_BYTE_DATA 0x08
+#define I801_WORD_DATA 0x0C
+#define I801_PROC_CALL 0x10 /* unimplemented */
+#define I801_BLOCK_DATA 0x14
+#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
+#define I801_BLOCK_PROC_CALL 0x1C
+
+/* I801 Host Control register bits */
+#define SMBHSTCNT_INTREN BIT(0)
+#define SMBHSTCNT_KILL BIT(1)
+#define SMBHSTCNT_LAST_BYTE BIT(5)
+#define SMBHSTCNT_START BIT(6)
+#define SMBHSTCNT_PEC_EN BIT(7) /* ICH3 and later */
+
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE BIT(7)
+#define SMBHSTSTS_INUSE_STS BIT(6)
+#define SMBHSTSTS_SMBALERT_STS BIT(5)
+#define SMBHSTSTS_FAILED BIT(4)
+#define SMBHSTSTS_BUS_ERR BIT(3)
+#define SMBHSTSTS_DEV_ERR BIT(2)
+#define SMBHSTSTS_INTR BIT(1)
+#define SMBHSTSTS_HOST_BUSY BIT(0)
+
+/* Host Notify Status register bits */
+#define SMBSLVSTS_HST_NTFY_STS BIT(0)
+
+/* Host Notify Command register bits */
+#define SMBSLVCMD_HST_NTFY_INTREN BIT(0)
+
+#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
+ SMBHSTSTS_DEV_ERR)
+
+#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \
+ STATUS_ERROR_FLAGS)
+
+/* Older devices have their ID defined in */
+#define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3
+#define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS 0x06a3
+#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12
+#define PCI_DEVICE_ID_INTEL_CDF_SMBUS 0x18df
+#define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df
+#define PCI_DEVICE_ID_INTEL_EBG_SMBUS 0x1bc9
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
+/* Patsburg also has three 'Integrated Device Function' SMBus controllers */
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
+#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c
+#define PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS 0x2292
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330
+#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0
+#define PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS 0x31d4
+#define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS 0x34a3
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
+#define PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS 0x43a3
+#define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23
+#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3
+#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
+#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0 0x8d7d
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2
+#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS 0x9d23
+#define PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS 0x9da3
+#define PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS 0xa0a3
+#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS 0xa123
+#define PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS 0xa1a3
+#define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS 0xa223
+#define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3
+#define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323
+#define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3
+
+struct i801_mux_config {
+ char *gpio_chip;
+ unsigned values[3];
+ int n_values;
+ unsigned classes[3];
+ unsigned gpios[2]; /* Relative to gpio_chip->base */
+ int n_gpios;
+};
+
+struct i801_priv {
+ struct i2c_adapter adapter;
+ unsigned long smba;
+ unsigned char original_hstcfg;
+ unsigned char original_slvcmd;
+ struct pci_dev *pci_dev;
+ unsigned int features;
+
+ /* isr processing */
+ wait_queue_head_t waitq;
+ u8 status;
+
+ /* Command state used by isr for byte-by-byte block transactions */
+ u8 cmd;
+ bool is_read;
+ int count;
+ int len;
+ u8 *data;
+
+#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
+ const struct i801_mux_config *mux_drvdata;
+ struct platform_device *mux_pdev;
+ struct gpiod_lookup_table *lookup;
+#endif
+ struct platform_device *tco_pdev;
+
+ /*
+ * If set to true the host controller registers are reserved for
+ * ACPI AML use. Protected by acpi_lock.
+ */
+ bool acpi_reserved;
+ struct mutex acpi_lock;
+};
+
+#define FEATURE_SMBUS_PEC BIT(0)
+#define FEATURE_BLOCK_BUFFER BIT(1)
+#define FEATURE_BLOCK_PROC BIT(2)
+#define FEATURE_I2C_BLOCK_READ BIT(3)
+#define FEATURE_IRQ BIT(4)
+#define FEATURE_HOST_NOTIFY BIT(5)
+/* Not really a feature, but it's convenient to handle it as such */
+#define FEATURE_IDF BIT(15)
+#define FEATURE_TCO_SPT BIT(16)
+#define FEATURE_TCO_CNL BIT(17)
+
+static const char *i801_feature_names[] = {
+ "SMBus PEC",
+ "Block buffer",
+ "Block process call",
+ "I2C block read",
+ "Interrupt",
+ "SMBus Host Notify",
+};
+
+static unsigned int disable_features;
+module_param(disable_features, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n"
+ "\t\t 0x01 disable SMBus PEC\n"
+ "\t\t 0x02 disable the block buffer\n"
+ "\t\t 0x08 disable the I2C block read functionality\n"
+ "\t\t 0x10 don't use interrupts\n"
+ "\t\t 0x20 disable SMBus Host Notify ");
+
+static void i801_setscl(struct i801_priv *priv, unsigned int level)
+{
+ int pin_status;
+ pin_status = inb_p(SMBPINCTL(priv));
+ if (level == 0) {
+ pin_status &= (~SMBPINCTL_CLK_CTL);
+ }
+ else {
+ pin_status |= SMBPINCTL_CLK_CTL;
+ }
+ outb_p(pin_status, SMBPINCTL(priv));
+ return;
+}
+
+static void i801_i2c_unblock(struct i801_priv *priv)
+{
+ int i;
+ for (i = 0; i < 10; i++) {
+ i801_setscl(priv, 0);
+ udelay(5);
+ i801_setscl(priv, 1);
+ udelay(5);
+ }
+ return;
+}
+
+static int i801_check_i2c_unblock(struct i801_priv *priv)
+{
+ int pin_status;
+
+ pin_status = inb_p(SMBPINCTL(priv));
+ if ( (!(pin_status & SMBPINCTL_SDA_STS) ) && (pin_status & SMBPINCTL_CLK_STS) ) {
+ dev_dbg(&priv->pci_dev->dev, "SDA is low, send 9 clock to device!\n");
+ i801_i2c_unblock(priv);
+ }
+ return 0;
+}
+
+static void i801_do_reset(struct i801_priv *priv)
+{
+ unsigned char tmp;
+ unsigned int retry_count = 0;
+
+ pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &tmp);
+ tmp |= SMBHSTCFG_SSRESET;
+ pci_write_config_byte(priv->pci_dev, SMBHSTCFG, tmp);
+ pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &tmp);
+
+ while( ((tmp & SMBHSTCFG_SSRESET) != 0) && (retry_count < SSRESET_RETRY_TIME)) {
+ usleep_range(SSRESET_SLEEP_TIME, SSRESET_SLEEP_TIME + 1);
+ retry_count++;
+ pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &tmp);
+ }
+
+ return ;
+}
+
+static int i801_check_i2c_scl(struct i801_priv *priv)
+{
+ int pin_status;
+
+ pin_status = inb_p(SMBPINCTL(priv));
+ if ( (pin_status & SMBPINCTL_SDA_STS) && (pin_status & SMBPINCTL_CLK_STS) ) {
+ return 0;
+ }
+
+ dev_dbg(&priv->pci_dev->dev, "SDA or SCL is low, begin to reset SMBus adapter, pin_status: 0x%x\n",pin_status);
+ i801_do_reset(priv);
+ pin_status = inb_p(SMBPINCTL(priv));
+ if ( (pin_status & SMBPINCTL_SDA_STS) && (pin_status & SMBPINCTL_CLK_STS) ) {
+ return 0;
+ }
+ dev_warn(&priv->pci_dev->dev, "SDA or SCL is low.pin_status:0x%x\n",pin_status);
+ return -1;
+}
+
+/* Make sure the SMBus host is ready to start transmitting.
+ Return 0 if it is, -EBUSY if it is not. */
+static int i801_check_pre(struct i801_priv *priv)
+{
+ int status;
+
+ i801_check_i2c_unblock(priv);
+
+ if (i801_check_i2c_scl(priv)) {
+ return -EIO;
+ }
+
+ status = inb_p(SMBHSTSTS(priv));
+ if (status & SMBHSTSTS_HOST_BUSY) {
+ dev_dbg(&priv->pci_dev->dev, "SMBus is busy, begin to reset SMBus adapter!\n");
+
+ i801_do_reset(priv);
+
+ status = inb_p(SMBHSTSTS(priv));
+ if (status & SMBHSTSTS_HOST_BUSY) {
+ dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n");
+ return -EBUSY;
+ }
+ }
+
+ status &= STATUS_FLAGS;
+ if (status) {
+ dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n",
+ status);
+ outb_p(status, SMBHSTSTS(priv));
+ status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
+ if (status) {
+ dev_err(&priv->pci_dev->dev,
+ "Failed clearing status flags (%02x)\n",
+ status);
+ return -EBUSY;
+ }
+ }
+
+ /*
+ * Clear CRC status if needed.
+ * During normal operation, i801_check_post() takes care
+ * of it after every operation. We do it here only in case
+ * the hardware was already in this state when the driver
+ * started.
+ */
+ if (priv->features & FEATURE_SMBUS_PEC) {
+ status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE;
+ if (status) {
+ dev_dbg(&priv->pci_dev->dev,
+ "Clearing aux status flags (%02x)\n", status);
+ outb_p(status, SMBAUXSTS(priv));
+ status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE;
+ if (status) {
+ dev_err(&priv->pci_dev->dev,
+ "Failed clearing aux status flags (%02x)\n",
+ status);
+ return -EBUSY;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Convert the status register to an error code, and clear it.
+ * Note that status only contains the bits we want to clear, not the
+ * actual register value.
+ */
+static int i801_check_post(struct i801_priv *priv, int status)
+{
+ int result = 0;
+
+ /*
+ * If the SMBus is still busy, we give up
+ * Note: This timeout condition only happens when using polling
+ * transactions. For interrupt operation, NAK/timeout is indicated by
+ * DEV_ERR.
+ */
+ if (unlikely(status < 0)) {
+ dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
+ /* try to stop the current command */
+ dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
+ outb_p(SMBHSTCNT_KILL, SMBHSTCNT(priv));
+ usleep_range(1000, 2000);
+ outb_p(0, SMBHSTCNT(priv));
+
+ /* Check if it worked */
+ status = inb_p(SMBHSTSTS(priv));
+ if ((status & SMBHSTSTS_HOST_BUSY) ||
+ !(status & SMBHSTSTS_FAILED))
+ dev_err(&priv->pci_dev->dev,
+ "Failed terminating the transaction\n");
+ outb_p(STATUS_FLAGS, SMBHSTSTS(priv));
+ return -ETIMEDOUT;
+ }
+
+ if (status & SMBHSTSTS_FAILED) {
+ result = -EIO;
+ dev_err(&priv->pci_dev->dev, "Transaction failed\n");
+ }
+ if (status & SMBHSTSTS_DEV_ERR) {
+ /*
+ * This may be a PEC error, check and clear it.
+ *
+ * AUXSTS is handled differently from HSTSTS.
+ * For HSTSTS, i801_isr() or i801_wait_intr()
+ * has already cleared the error bits in hardware,
+ * and we are passed a copy of the original value
+ * in "status".
+ * For AUXSTS, the hardware register is left
+ * for us to handle here.
+ * This is asymmetric, slightly iffy, but safe,
+ * since all this code is serialized and the CRCE
+ * bit is harmless as long as it's cleared before
+ * the next operation.
+ */
+ if ((priv->features & FEATURE_SMBUS_PEC) &&
+ (inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE)) {
+ outb_p(SMBAUXSTS_CRCE, SMBAUXSTS(priv));
+ result = -EBADMSG;
+ dev_dbg(&priv->pci_dev->dev, "PEC error\n");
+ } else {
+ result = -ENXIO;
+ dev_dbg(&priv->pci_dev->dev, "No response\n");
+ }
+ }
+ if (status & SMBHSTSTS_BUS_ERR) {
+ result = -EAGAIN;
+ dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n");
+ }
+
+ /* Clear status flags except BYTE_DONE, to be cleared by caller */
+ outb_p(status, SMBHSTSTS(priv));
+
+ return result;
+}
+
+/* Wait for BUSY being cleared and either INTR or an error flag being set */
+static int i801_wait_intr(struct i801_priv *priv)
+{
+ int timeout = 0;
+ int status;
+
+ /* We will always wait for a fraction of a second! */
+ do {
+ usleep_range(250, 500);
+ status = inb_p(SMBHSTSTS(priv));
+ } while (((status & SMBHSTSTS_HOST_BUSY) ||
+ !(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) &&
+ (timeout++ < MAX_RETRIES));
+
+ if (timeout > MAX_RETRIES) {
+ dev_dbg(&priv->pci_dev->dev, "INTR Timeout!\n");
+ return -ETIMEDOUT;
+ }
+ return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR);
+}
+
+/* Wait for either BYTE_DONE or an error flag being set */
+static int i801_wait_byte_done(struct i801_priv *priv)
+{
+ int timeout = 0;
+ int status;
+
+ /* We will always wait for a fraction of a second! */
+ do {
+ usleep_range(250, 500);
+ status = inb_p(SMBHSTSTS(priv));
+ } while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) &&
+ (timeout++ < MAX_RETRIES));
+
+ if (timeout > MAX_RETRIES) {
+ dev_dbg(&priv->pci_dev->dev, "BYTE_DONE Timeout!\n");
+ return -ETIMEDOUT;
+ }
+ return status & STATUS_ERROR_FLAGS;
+}
+
+static int i801_transaction(struct i801_priv *priv, int xact)
+{
+ int status;
+ int result;
+ const struct i2c_adapter *adap = &priv->adapter;
+
+ result = i801_check_pre(priv);
+ if (result < 0)
+ return result;
+
+ if (priv->features & FEATURE_IRQ) {
+ outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
+ SMBHSTCNT(priv));
+ result = wait_event_timeout(priv->waitq,
+ (status = priv->status),
+ adap->timeout);
+ if (!result) {
+ status = -ETIMEDOUT;
+ dev_warn(&priv->pci_dev->dev,
+ "Timeout waiting for interrupt!\n");
+ }
+ priv->status = 0;
+ return i801_check_post(priv, status);
+ }
+
+ /* the current contents of SMBHSTCNT can be overwritten, since PEC,
+ * SMBSCMD are passed in xact */
+ outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
+
+ status = i801_wait_intr(priv);
+ return i801_check_post(priv, status);
+}
+
+static int i801_block_transaction_by_block(struct i801_priv *priv,
+ union i2c_smbus_data *data,
+ char read_write, int command,
+ int hwpec)
+{
+ int i, len;
+ int status;
+ int xact = hwpec ? SMBHSTCNT_PEC_EN : 0;
+
+ switch (command) {
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ xact |= I801_BLOCK_PROC_CALL;
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ xact |= I801_BLOCK_DATA;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
+
+ /* Use 32-byte buffer to process this transaction */
+ if (read_write == I2C_SMBUS_WRITE) {
+ len = data->block[0];
+ outb_p(len, SMBHSTDAT0(priv));
+ for (i = 0; i < len; i++)
+ outb_p(data->block[i+1], SMBBLKDAT(priv));
+ }
+
+ status = i801_transaction(priv, xact);
+ if (status)
+ return status;
+
+ if (read_write == I2C_SMBUS_READ ||
+ command == I2C_SMBUS_BLOCK_PROC_CALL) {
+ len = inb_p(SMBHSTDAT0(priv));
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+ return -EPROTO;
+
+ data->block[0] = len;
+ for (i = 0; i < len; i++)
+ data->block[i + 1] = inb_p(SMBBLKDAT(priv));
+ }
+ return 0;
+}
+
+static void i801_isr_byte_done(struct i801_priv *priv)
+{
+ if (priv->is_read) {
+ /* For SMBus block reads, length is received with first byte */
+ if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) &&
+ (priv->count == 0)) {
+ priv->len = inb_p(SMBHSTDAT0(priv));
+ if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) {
+ dev_err(&priv->pci_dev->dev,
+ "Illegal SMBus block read size %d\n",
+ priv->len);
+ /* FIXME: Recover */
+ priv->len = I2C_SMBUS_BLOCK_MAX;
+ } else {
+ dev_dbg(&priv->pci_dev->dev,
+ "SMBus block read size is %d\n",
+ priv->len);
+ }
+ priv->data[-1] = priv->len;
+ }
+
+ /* Read next byte */
+ if (priv->count < priv->len)
+ priv->data[priv->count++] = inb(SMBBLKDAT(priv));
+ else
+ dev_dbg(&priv->pci_dev->dev,
+ "Discarding extra byte on block read\n");
+
+ /* Set LAST_BYTE for last byte of read transaction */
+ if (priv->count == priv->len - 1)
+ outb_p(priv->cmd | SMBHSTCNT_LAST_BYTE,
+ SMBHSTCNT(priv));
+ } else if (priv->count < priv->len - 1) {
+ /* Write next byte, except for IRQ after last byte */
+ outb_p(priv->data[++priv->count], SMBBLKDAT(priv));
+ }
+
+ /* Clear BYTE_DONE to continue with next byte */
+ outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
+}
+
+static irqreturn_t i801_host_notify_isr(struct i801_priv *priv)
+{
+ unsigned short addr;
+
+ addr = inb_p(SMBNTFDADD(priv)) >> 1;
+
+ /*
+ * With the tested platforms, reading SMBNTFDDAT (22 + (p)->smba)
+ * always returns 0. Our current implementation doesn't provide
+ * data, so we just ignore it.
+ */
+ i2c_handle_smbus_host_notify(&priv->adapter, addr);
+
+ /* clear Host Notify bit and return */
+ outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv));
+ return IRQ_HANDLED;
+}
+
+/*
+ * There are three kinds of interrupts:
+ *
+ * 1) i801 signals transaction completion with one of these interrupts:
+ * INTR - Success
+ * DEV_ERR - Invalid command, NAK or communication timeout
+ * BUS_ERR - SMI# transaction collision
+ * FAILED - transaction was canceled due to a KILL request
+ * When any of these occur, update ->status and wake up the waitq.
+ * ->status must be cleared before kicking off the next transaction.
+ *
+ * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt
+ * occurs for each byte of a byte-by-byte to prepare the next byte.
+ *
+ * 3) Host Notify interrupts
+ */
+static irqreturn_t i801_isr(int irq, void *dev_id)
+{
+ struct i801_priv *priv = dev_id;
+ u16 pcists;
+ u8 status;
+
+ /* Confirm this is our interrupt */
+ pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists);
+ if (!(pcists & SMBPCISTS_INTS))
+ return IRQ_NONE;
+
+ if (priv->features & FEATURE_HOST_NOTIFY) {
+ status = inb_p(SMBSLVSTS(priv));
+ if (status & SMBSLVSTS_HST_NTFY_STS)
+ return i801_host_notify_isr(priv);
+ }
+
+ status = inb_p(SMBHSTSTS(priv));
+ if (status & SMBHSTSTS_BYTE_DONE)
+ i801_isr_byte_done(priv);
+
+ /*
+ * Clear irq sources and report transaction result.
+ * ->status must be cleared before the next transaction is started.
+ */
+ status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS;
+ if (status) {
+ outb_p(status, SMBHSTSTS(priv));
+ priv->status = status;
+ wake_up(&priv->waitq);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * For "byte-by-byte" block transactions:
+ * I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1
+ * I2C read uses cmd=I801_I2C_BLOCK_DATA
+ */
+static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
+ union i2c_smbus_data *data,
+ char read_write, int command,
+ int hwpec)
+{
+ int i, len;
+ int smbcmd;
+ int status;
+ int result;
+ const struct i2c_adapter *adap = &priv->adapter;
+
+ if (command == I2C_SMBUS_BLOCK_PROC_CALL)
+ return -EOPNOTSUPP;
+
+ result = i801_check_pre(priv);
+ if (result < 0)
+ return result;
+
+ len = data->block[0];
+
+ if (read_write == I2C_SMBUS_WRITE) {
+ outb_p(len, SMBHSTDAT0(priv));
+ outb_p(data->block[1], SMBBLKDAT(priv));
+ }
+
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA &&
+ read_write == I2C_SMBUS_READ)
+ smbcmd = I801_I2C_BLOCK_DATA;
+ else
+ smbcmd = I801_BLOCK_DATA;
+
+ if (priv->features & FEATURE_IRQ) {
+ priv->is_read = (read_write == I2C_SMBUS_READ);
+ if (len == 1 && priv->is_read)
+ smbcmd |= SMBHSTCNT_LAST_BYTE;
+ priv->cmd = smbcmd | SMBHSTCNT_INTREN;
+ priv->len = len;
+ priv->count = 0;
+ priv->data = &data->block[1];
+
+ outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));
+ result = wait_event_timeout(priv->waitq,
+ (status = priv->status),
+ adap->timeout);
+ if (!result) {
+ status = -ETIMEDOUT;
+ dev_warn(&priv->pci_dev->dev,
+ "Timeout waiting for interrupt!\n");
+ }
+ priv->status = 0;
+ return i801_check_post(priv, status);
+ }
+
+ for (i = 1; i <= len; i++) {
+ if (i == len && read_write == I2C_SMBUS_READ)
+ smbcmd |= SMBHSTCNT_LAST_BYTE;
+ outb_p(smbcmd, SMBHSTCNT(priv));
+
+ if (i == 1)
+ outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
+ SMBHSTCNT(priv));
+
+ status = i801_wait_byte_done(priv);
+ if (status)
+ goto exit;
+
+ if (i == 1 && read_write == I2C_SMBUS_READ
+ && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+ len = inb_p(SMBHSTDAT0(priv));
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
+ dev_err(&priv->pci_dev->dev,
+ "Illegal SMBus block read size %d\n",
+ len);
+ /* Recover */
+ while (inb_p(SMBHSTSTS(priv)) &
+ SMBHSTSTS_HOST_BUSY)
+ outb_p(SMBHSTSTS_BYTE_DONE,
+ SMBHSTSTS(priv));
+ outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv));
+ return -EPROTO;
+ }
+ data->block[0] = len;
+ }
+
+ /* Retrieve/store value in SMBBLKDAT */
+ if (read_write == I2C_SMBUS_READ)
+ data->block[i] = inb_p(SMBBLKDAT(priv));
+ if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
+ outb_p(data->block[i+1], SMBBLKDAT(priv));
+
+ /* signals SMBBLKDAT ready */
+ outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
+ }
+
+ status = i801_wait_intr(priv);
+exit:
+ return i801_check_post(priv, status);
+}
+
+static int i801_set_block_buffer_mode(struct i801_priv *priv)
+{
+ outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
+ if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
+ return -EIO;
+ return 0;
+}
+
+/* Block transaction function */
+static int i801_block_transaction(struct i801_priv *priv,
+ union i2c_smbus_data *data, char read_write,
+ int command, int hwpec)
+{
+ int result = 0;
+ unsigned char hostc;
+
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (read_write == I2C_SMBUS_WRITE) {
+ /* set I2C_EN bit in configuration register */
+ pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
+ pci_write_config_byte(priv->pci_dev, SMBHSTCFG,
+ hostc | SMBHSTCFG_I2C_EN);
+ } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
+ dev_err(&priv->pci_dev->dev,
+ "I2C block read is unsupported!\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ if (read_write == I2C_SMBUS_WRITE
+ || command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (data->block[0] < 1)
+ data->block[0] = 1;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ } else {
+ data->block[0] = 32; /* max for SMBus block reads */
+ }
+
+ /* Experience has shown that the block buffer can only be used for
+ SMBus (not I2C) block transactions, even though the datasheet
+ doesn't mention this limitation. */
+ if ((priv->features & FEATURE_BLOCK_BUFFER)
+ && command != I2C_SMBUS_I2C_BLOCK_DATA
+ && i801_set_block_buffer_mode(priv) == 0)
+ result = i801_block_transaction_by_block(priv, data,
+ read_write,
+ command, hwpec);
+ else
+ result = i801_block_transaction_byte_by_byte(priv, data,
+ read_write,
+ command, hwpec);
+
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA
+ && read_write == I2C_SMBUS_WRITE) {
+ /* restore saved configuration register value */
+ pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
+ }
+ return result;
+}
+
+/* Return negative errno on error. */
+static s32 i801_access(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ int hwpec;
+ int block = 0;
+ int ret = 0, xact = 0;
+ struct i801_priv *priv = i2c_get_adapdata(adap);
+
+ mutex_lock(&priv->acpi_lock);
+ if (priv->acpi_reserved) {
+ mutex_unlock(&priv->acpi_lock);
+ return -EBUSY;
+ }
+
+ pm_runtime_get_sync(&priv->pci_dev->dev);
+
+ hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
+ && size != I2C_SMBUS_QUICK
+ && size != I2C_SMBUS_I2C_BLOCK_DATA;
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+ xact = I801_QUICK;
+ break;
+ case I2C_SMBUS_BYTE:
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+ if (read_write == I2C_SMBUS_WRITE)
+ outb_p(command, SMBHSTCMD(priv));
+ xact = I801_BYTE;
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+ outb_p(command, SMBHSTCMD(priv));
+ if (read_write == I2C_SMBUS_WRITE)
+ outb_p(data->byte, SMBHSTDAT0(priv));
+ xact = I801_BYTE_DATA;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+ outb_p(command, SMBHSTCMD(priv));
+ if (read_write == I2C_SMBUS_WRITE) {
+ outb_p(data->word & 0xff, SMBHSTDAT0(priv));
+ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
+ }
+ xact = I801_WORD_DATA;
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMBHSTADD(priv));
+ outb_p(command, SMBHSTCMD(priv));
+ block = 1;
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ /*
+ * NB: page 240 of ICH5 datasheet shows that the R/#W
+ * bit should be cleared here, even when reading.
+ * However if SPD Write Disable is set (Lynx Point and later),
+ * the read will fail if we don't set the R/#W bit.
+ */
+ outb_p(((addr & 0x7f) << 1) |
+ ((priv->original_hstcfg & SMBHSTCFG_SPD_WD) ?
+ (read_write & 0x01) : 0),
+ SMBHSTADD(priv));
+ if (read_write == I2C_SMBUS_READ) {
+ /* NB: page 240 of ICH5 datasheet also shows
+ * that DATA1 is the cmd field when reading */
+ outb_p(command, SMBHSTDAT1(priv));
+ } else
+ outb_p(command, SMBHSTCMD(priv));
+ block = 1;
+ break;
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ /*
+ * Bit 0 of the slave address register always indicate a write
+ * command.
+ */
+ outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
+ outb_p(command, SMBHSTCMD(priv));
+ block = 1;
+ break;
+ default:
+ dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
+ size);
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (hwpec) /* enable/disable hardware PEC */
+ outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
+ else
+ outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
+ SMBAUXCTL(priv));
+
+ if (block)
+ ret = i801_block_transaction(priv, data, read_write, size,
+ hwpec);
+ else
+ ret = i801_transaction(priv, xact);
+
+ /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+ time, so we forcibly disable it after every transaction. Turn off
+ E32B for the same reason. */
+ if (hwpec || block)
+ outb_p(inb_p(SMBAUXCTL(priv)) &
+ ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
+
+ if (block)
+ goto out;
+ if (ret)
+ goto out;
+ if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
+ goto out;
+
+ switch (xact & 0x7f) {
+ case I801_BYTE: /* Result put in SMBHSTDAT0 */
+ case I801_BYTE_DATA:
+ data->byte = inb_p(SMBHSTDAT0(priv));
+ break;
+ case I801_WORD_DATA:
+ data->word = inb_p(SMBHSTDAT0(priv)) +
+ (inb_p(SMBHSTDAT1(priv)) << 8);
+ break;
+ }
+
+out:
+ pm_runtime_mark_last_busy(&priv->pci_dev->dev);
+ pm_runtime_put_autosuspend(&priv->pci_dev->dev);
+ mutex_unlock(&priv->acpi_lock);
+ return ret;
+}
+
+static u32 i801_func(struct i2c_adapter *adapter)
+{
+ struct i801_priv *priv = i2c_get_adapdata(adapter);
+
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
+ ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
+ ((priv->features & FEATURE_BLOCK_PROC) ?
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL : 0) |
+ ((priv->features & FEATURE_I2C_BLOCK_READ) ?
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) |
+ ((priv->features & FEATURE_HOST_NOTIFY) ?
+ I2C_FUNC_SMBUS_HOST_NOTIFY : 0);
+}
+
+static void i801_enable_host_notify(struct i2c_adapter *adapter)
+{
+ struct i801_priv *priv = i2c_get_adapdata(adapter);
+
+ if (!(priv->features & FEATURE_HOST_NOTIFY))
+ return;
+
+ if (!(SMBSLVCMD_HST_NTFY_INTREN & priv->original_slvcmd))
+ outb_p(SMBSLVCMD_HST_NTFY_INTREN | priv->original_slvcmd,
+ SMBSLVCMD(priv));
+
+ /* clear Host Notify bit to allow a new notification */
+ outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv));
+}
+
+static void i801_disable_host_notify(struct i801_priv *priv)
+{
+ if (!(priv->features & FEATURE_HOST_NOTIFY))
+ return;
+
+ outb_p(priv->original_slvcmd, SMBSLVCMD(priv));
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+ .smbus_xfer = i801_access,
+ .functionality = i801_func,
+};
+
+static const struct pci_device_id i801_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EBG_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS) },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, i801_ids);
+
+#if defined CONFIG_X86 && defined CONFIG_DMI
+static unsigned char apanel_addr;
+
+/* Scan the system ROM for the signature "FJKEYINF" */
+static __init const void __iomem *bios_signature(const void __iomem *bios)
+{
+ ssize_t offset;
+ const unsigned char signature[] = "FJKEYINF";
+
+ for (offset = 0; offset < 0x10000; offset += 0x10) {
+ if (check_signature(bios + offset, signature,
+ sizeof(signature)-1))
+ return bios + offset;
+ }
+ return NULL;
+}
+
+static void __init input_apanel_init(void)
+{
+ void __iomem *bios;
+ const void __iomem *p;
+
+ bios = ioremap(0xF0000, 0x10000); /* Can't fail */
+ p = bios_signature(bios);
+ if (p) {
+ /* just use the first address */
+ apanel_addr = readb(p + 8 + 3) >> 1;
+ }
+ iounmap(bios);
+}
+
+struct dmi_onboard_device_info {
+ const char *name;
+ u8 type;
+ unsigned short i2c_addr;
+ const char *i2c_type;
+};
+
+static const struct dmi_onboard_device_info dmi_devices[] = {
+ { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
+ { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
+ { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
+};
+
+static void dmi_check_onboard_device(u8 type, const char *name,
+ struct i2c_adapter *adap)
+{
+ int i;
+ struct i2c_board_info info;
+
+ for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) {
+ /* & ~0x80, ignore enabled/disabled bit */
+ if ((type & ~0x80) != dmi_devices[i].type)
+ continue;
+ if (strcasecmp(name, dmi_devices[i].name))
+ continue;
+
+ mem_clear(&info, sizeof(struct i2c_board_info));
+ info.addr = dmi_devices[i].i2c_addr;
+ strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
+ i2c_new_client_device(adap, &info);
+ break;
+ }
+}
+
+/* We use our own function to check for onboard devices instead of
+ dmi_find_device() as some buggy BIOS's have the devices we are interested
+ in marked as disabled */
+static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap)
+{
+ int i, count;
+
+ if (dm->type != 10)
+ return;
+
+ count = (dm->length - sizeof(struct dmi_header)) / 2;
+ for (i = 0; i < count; i++) {
+ const u8 *d = (char *)(dm + 1) + (i * 2);
+ const char *name = ((char *) dm) + dm->length;
+ u8 type = d[0];
+ u8 s = d[1];
+
+ if (!s)
+ continue;
+ s--;
+ while (s > 0 && name[0]) {
+ name += strlen(name) + 1;
+ s--;
+ }
+ if (name[0] == 0) /* Bogus string reference */
+ continue;
+
+ dmi_check_onboard_device(type, name, adap);
+ }
+}
+
+/* NOTE: Keep this list in sync with drivers/platform/x86/dell-smo8800.c */
+static const char *const acpi_smo8800_ids[] = {
+ "SMO8800",
+ "SMO8801",
+ "SMO8810",
+ "SMO8811",
+ "SMO8820",
+ "SMO8821",
+ "SMO8830",
+ "SMO8831",
+};
+
+static acpi_status check_acpi_smo88xx_device(acpi_handle obj_handle,
+ u32 nesting_level,
+ void *context,
+ void **return_value)
+{
+ struct acpi_device_info *info;
+ acpi_status status;
+ char *hid;
+ int i;
+
+ status = acpi_get_object_info(obj_handle, &info);
+ if (ACPI_FAILURE(status))
+ return AE_OK;
+
+ if (!(info->valid & ACPI_VALID_HID))
+ goto smo88xx_not_found;
+
+ hid = info->hardware_id.string;
+ if (!hid)
+ goto smo88xx_not_found;
+
+ i = match_string(acpi_smo8800_ids, ARRAY_SIZE(acpi_smo8800_ids), hid);
+ if (i < 0)
+ goto smo88xx_not_found;
+
+ kfree(info);
+
+ *((bool *)return_value) = true;
+ return AE_CTRL_TERMINATE;
+
+smo88xx_not_found:
+ kfree(info);
+ return AE_OK;
+}
+
+static bool is_dell_system_with_lis3lv02d(void)
+{
+ bool found;
+ const char *vendor;
+
+ vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+ if (!vendor || strcmp(vendor, "Dell Inc."))
+ return false;
+
+ /*
+ * Check that ACPI device SMO88xx is present and is functioning.
+ * Function acpi_get_devices() already filters all ACPI devices
+ * which are not present or are not functioning.
+ * ACPI device SMO88xx represents our ST microelectronics lis3lv02d
+ * accelerometer but unfortunately ACPI does not provide any other
+ * information (like I2C address).
+ */
+ found = false;
+ acpi_get_devices(NULL, check_acpi_smo88xx_device, NULL,
+ (void **)&found);
+
+ return found;
+}
+
+/*
+ * Accelerometer's I2C address is not specified in DMI nor ACPI,
+ * so it is needed to define mapping table based on DMI product names.
+ */
+static const struct {
+ const char *dmi_product_name;
+ unsigned short i2c_addr;
+} dell_lis3lv02d_devices[] = {
+ /*
+ * Dell platform team told us that these Latitude devices have
+ * ST microelectronics accelerometer at I2C address 0x29.
+ */
+ { "Latitude E5250", 0x29 },
+ { "Latitude E5450", 0x29 },
+ { "Latitude E5550", 0x29 },
+ { "Latitude E6440", 0x29 },
+ { "Latitude E6440 ATG", 0x29 },
+ { "Latitude E6540", 0x29 },
+ /*
+ * Additional individual entries were added after verification.
+ */
+ { "Latitude 5480", 0x29 },
+ { "Vostro V131", 0x1d },
+};
+
+static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv)
+{
+ struct i2c_board_info info;
+ const char *dmi_product_name;
+ int i;
+
+ dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
+ for (i = 0; i < ARRAY_SIZE(dell_lis3lv02d_devices); ++i) {
+ if (strcmp(dmi_product_name,
+ dell_lis3lv02d_devices[i].dmi_product_name) == 0)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(dell_lis3lv02d_devices)) {
+ dev_warn(&priv->pci_dev->dev,
+ "Accelerometer lis3lv02d is present on SMBus but its"
+ " address is unknown, skipping registration\n");
+ return;
+ }
+
+ mem_clear(&info, sizeof(struct i2c_board_info));
+ info.addr = dell_lis3lv02d_devices[i].i2c_addr;
+ strlcpy(info.type, "lis3lv02d", I2C_NAME_SIZE);
+ i2c_new_client_device(&priv->adapter, &info);
+}
+
+/* Register optional slaves */
+static void i801_probe_optional_slaves(struct i801_priv *priv)
+{
+ /* Only register slaves on main SMBus channel */
+ if (priv->features & FEATURE_IDF)
+ return;
+
+ if (apanel_addr) {
+ struct i2c_board_info info;
+
+ mem_clear(&info, sizeof(struct i2c_board_info));
+ info.addr = apanel_addr;
+ strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE);
+ i2c_new_client_device(&priv->adapter, &info);
+ }
+
+ if (dmi_name_in_vendors("FUJITSU"))
+ dmi_walk(dmi_check_onboard_devices, &priv->adapter);
+
+ if (is_dell_system_with_lis3lv02d())
+ register_dell_lis3lv02d_i2c_device(priv);
+
+ /* Instantiate SPD EEPROMs unless the SMBus is multiplexed */
+#if IS_ENABLED(CONFIG_I2C_MUX_GPIO)
+ if (!priv->mux_drvdata)
+#endif
+ i2c_register_spd(&priv->adapter);
+}
+#else
+static void __init input_apanel_init(void) {}
+static void i801_probe_optional_slaves(struct i801_priv *priv) {}
+#endif /* CONFIG_X86 && CONFIG_DMI */
+
+#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
+static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
+ .gpio_chip = "gpio_ich",
+ .values = { 0x02, 0x03 },
+ .n_values = 2,
+ .classes = { I2C_CLASS_SPD, I2C_CLASS_SPD },
+ .gpios = { 52, 53 },
+ .n_gpios = 2,
+};
+
+static struct i801_mux_config i801_mux_config_asus_z8_d18 = {
+ .gpio_chip = "gpio_ich",
+ .values = { 0x02, 0x03, 0x01 },
+ .n_values = 3,
+ .classes = { I2C_CLASS_SPD, I2C_CLASS_SPD, I2C_CLASS_SPD },
+ .gpios = { 52, 53 },
+ .n_gpios = 2,
+};
+
+static const struct dmi_system_id mux_dmi_table[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8NA-D6(C)"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d12,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)E-D12(X)"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d12,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8NH-D12"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d12,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8PH-D12/IFB"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d12,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8NR-D12"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d12,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)H-D12"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d12,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8PG-D18"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d18,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8PE-D18"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d18,
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "Z8PS-D12"),
+ },
+ .driver_data = &i801_mux_config_asus_z8_d12,
+ },
+ { }
+};
+
+/* Setup multiplexing if needed */
+static int i801_add_mux(struct i801_priv *priv)
+{
+ struct device *dev = &priv->adapter.dev;
+ const struct i801_mux_config *mux_config;
+ struct i2c_mux_gpio_platform_data gpio_data;
+ struct gpiod_lookup_table *lookup;
+ int err, i;
+
+ if (!priv->mux_drvdata)
+ return 0;
+ mux_config = priv->mux_drvdata;
+
+ /* Prepare the platform data */
+ mem_clear(&gpio_data, sizeof(struct i2c_mux_gpio_platform_data));
+ gpio_data.parent = priv->adapter.nr;
+ gpio_data.values = mux_config->values;
+ gpio_data.n_values = mux_config->n_values;
+ gpio_data.classes = mux_config->classes;
+ gpio_data.idle = I2C_MUX_GPIO_NO_IDLE;
+
+ /* Register GPIO descriptor lookup table */
+ lookup = devm_kzalloc(dev,
+ struct_size(lookup, table, mux_config->n_gpios + 1),
+ GFP_KERNEL);
+ if (!lookup)
+ return -ENOMEM;
+ lookup->dev_id = "i2c-mux-gpio";
+ for (i = 0; i < mux_config->n_gpios; i++) {
+ lookup->table[i] = (struct gpiod_lookup)
+ GPIO_LOOKUP(mux_config->gpio_chip,
+ mux_config->gpios[i], "mux", 0);
+ }
+ gpiod_add_lookup_table(lookup);
+ priv->lookup = lookup;
+
+ /*
+ * Register the mux device, we use PLATFORM_DEVID_NONE here
+ * because since we are referring to the GPIO chip by name we are
+ * anyways in deep trouble if there is more than one of these
+ * devices, and there should likely only be one platform controller
+ * hub.
+ */
+ priv->mux_pdev = platform_device_register_data(dev, "i2c-mux-gpio",
+ PLATFORM_DEVID_NONE, &gpio_data,
+ sizeof(struct i2c_mux_gpio_platform_data));
+ if (IS_ERR(priv->mux_pdev)) {
+ err = PTR_ERR(priv->mux_pdev);
+ gpiod_remove_lookup_table(lookup);
+ priv->mux_pdev = NULL;
+ dev_err(dev, "Failed to register i2c-mux-gpio device\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static void i801_del_mux(struct i801_priv *priv)
+{
+ if (priv->mux_pdev)
+ platform_device_unregister(priv->mux_pdev);
+ if (priv->lookup)
+ gpiod_remove_lookup_table(priv->lookup);
+}
+
+static unsigned int i801_get_adapter_class(struct i801_priv *priv)
+{
+ const struct dmi_system_id *id;
+ const struct i801_mux_config *mux_config;
+ unsigned int class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ int i;
+
+ id = dmi_first_match(mux_dmi_table);
+ if (id) {
+ /* Remove branch classes from trunk */
+ mux_config = id->driver_data;
+ for (i = 0; i < mux_config->n_values; i++)
+ class &= ~mux_config->classes[i];
+
+ /* Remember for later */
+ priv->mux_drvdata = mux_config;
+ }
+
+ return class;
+}
+#else
+static inline int i801_add_mux(struct i801_priv *priv) { return 0; }
+static inline void i801_del_mux(struct i801_priv *priv) { }
+
+static inline unsigned int i801_get_adapter_class(struct i801_priv *priv)
+{
+ return I2C_CLASS_HWMON | I2C_CLASS_SPD;
+}
+#endif
+
+static const struct itco_wdt_platform_data spt_tco_platform_data = {
+ .name = "Intel PCH",
+ .version = 4,
+};
+
+static DEFINE_SPINLOCK(p2sb_spinlock);
+
+static struct platform_device *
+i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
+ struct resource *tco_res)
+{
+ struct resource *res;
+ unsigned int devfn;
+ u64 base64_addr;
+ u32 base_addr;
+ u8 hidden;
+
+ /*
+ * We must access the NO_REBOOT bit over the Primary to Sideband
+ * bridge (P2SB). The BIOS prevents the P2SB device from being
+ * enumerated by the PCI subsystem, so we need to unhide/hide it
+ * to lookup the P2SB BAR.
+ */
+ spin_lock(&p2sb_spinlock);
+
+ devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1);
+
+ /* Unhide the P2SB device, if it is hidden */
+ pci_bus_read_config_byte(pci_dev->bus, devfn, 0xe1, &hidden);
+ if (hidden)
+ pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x0);
+
+ pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR, &base_addr);
+ base64_addr = base_addr & 0xfffffff0;
+
+ pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR + 0x4, &base_addr);
+ base64_addr |= (u64)base_addr << 32;
+
+ /* Hide the P2SB device, if it was hidden before */
+ if (hidden)
+ pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden);
+ spin_unlock(&p2sb_spinlock);
+
+ res = &tco_res[1];
+ if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
+ res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV;
+ else
+ res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL;
+
+ res->end = res->start + 3;
+ res->flags = IORESOURCE_MEM;
+
+ return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1,
+ tco_res, 2, &spt_tco_platform_data,
+ sizeof(spt_tco_platform_data));
+}
+
+static const struct itco_wdt_platform_data cnl_tco_platform_data = {
+ .name = "Intel PCH",
+ .version = 6,
+};
+
+static struct platform_device *
+i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev,
+ struct resource *tco_res)
+{
+ return platform_device_register_resndata(&pci_dev->dev,
+ "iTCO_wdt", -1, tco_res, 1, &cnl_tco_platform_data,
+ sizeof(cnl_tco_platform_data));
+}
+
+static void i801_add_tco(struct i801_priv *priv)
+{
+ struct pci_dev *pci_dev = priv->pci_dev;
+ struct resource tco_res[2], *res;
+ u32 tco_base, tco_ctl;
+
+ /* If we have ACPI based watchdog use that instead */
+ if (acpi_has_watchdog())
+ return;
+
+ if (!(priv->features & (FEATURE_TCO_SPT | FEATURE_TCO_CNL)))
+ return;
+
+ pci_read_config_dword(pci_dev, TCOBASE, &tco_base);
+ pci_read_config_dword(pci_dev, TCOCTL, &tco_ctl);
+ if (!(tco_ctl & TCOCTL_EN))
+ return;
+
+ mem_clear(tco_res, sizeof(tco_res));
+ /*
+ * Always populate the main iTCO IO resource here. The second entry
+ * for NO_REBOOT MMIO is filled by the SPT specific function.
+ */
+ res = &tco_res[0];
+ res->start = tco_base & ~1;
+ res->end = res->start + 32 - 1;
+ res->flags = IORESOURCE_IO;
+
+ if (priv->features & FEATURE_TCO_CNL)
+ priv->tco_pdev = i801_add_tco_cnl(priv, pci_dev, tco_res);
+ else
+ priv->tco_pdev = i801_add_tco_spt(priv, pci_dev, tco_res);
+
+ if (IS_ERR(priv->tco_pdev))
+ dev_warn(&pci_dev->dev, "failed to create iTCO device\n");
+}
+
+#ifdef CONFIG_ACPI
+static bool i801_acpi_is_smbus_ioport(const struct i801_priv *priv,
+ acpi_physical_address address)
+{
+ return address >= priv->smba &&
+ address <= pci_resource_end(priv->pci_dev, SMBBAR);
+}
+
+static acpi_status
+i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
+ u64 *value, void *handler_context, void *region_context)
+{
+ struct i801_priv *priv = handler_context;
+ struct pci_dev *pdev = priv->pci_dev;
+ acpi_status status;
+
+ /*
+ * Once BIOS AML code touches the OpRegion we warn and inhibit any
+ * further access from the driver itself. This device is now owned
+ * by the system firmware.
+ */
+ mutex_lock(&priv->acpi_lock);
+
+ if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) {
+ priv->acpi_reserved = true;
+
+ dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n");
+ dev_warn(&pdev->dev, "Driver SMBus register access inhibited\n");
+
+ /*
+ * BIOS is accessing the host controller so prevent it from
+ * suspending automatically from now on.
+ */
+ pm_runtime_get_sync(&pdev->dev);
+ }
+
+ if ((function & ACPI_IO_MASK) == ACPI_READ)
+ status = acpi_os_read_port(address, (u32 *)value, bits);
+ else
+ status = acpi_os_write_port(address, (u32)*value, bits);
+
+ mutex_unlock(&priv->acpi_lock);
+
+ return status;
+}
+
+static int i801_acpi_probe(struct i801_priv *priv)
+{
+ struct acpi_device *adev;
+ acpi_status status;
+
+ adev = ACPI_COMPANION(&priv->pci_dev->dev);
+ if (adev) {
+ status = acpi_install_address_space_handler(adev->handle,
+ ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler,
+ NULL, priv);
+ if (ACPI_SUCCESS(status))
+ return 0;
+ }
+
+ return acpi_check_resource_conflict(&priv->pci_dev->resource[SMBBAR]);
+}
+
+static void i801_acpi_remove(struct i801_priv *priv)
+{
+ struct acpi_device *adev;
+
+ adev = ACPI_COMPANION(&priv->pci_dev->dev);
+ if (!adev)
+ return;
+
+ acpi_remove_address_space_handler(adev->handle,
+ ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler);
+
+ mutex_lock(&priv->acpi_lock);
+ if (priv->acpi_reserved)
+ pm_runtime_put(&priv->pci_dev->dev);
+ mutex_unlock(&priv->acpi_lock);
+}
+#else
+static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
+static inline void i801_acpi_remove(struct i801_priv *priv) { }
+#endif
+
+static unsigned char i801_setup_hstcfg(struct i801_priv *priv)
+{
+ unsigned char hstcfg = priv->original_hstcfg;
+
+ hstcfg &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */
+ hstcfg |= SMBHSTCFG_HST_EN;
+ pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg);
+ return hstcfg;
+}
+
+static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ unsigned char temp;
+ int err, i;
+ struct i801_priv *priv;
+
+ priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ i2c_set_adapdata(&priv->adapter, priv);
+ priv->adapter.owner = THIS_MODULE;
+ priv->adapter.class = i801_get_adapter_class(priv);
+ priv->adapter.algo = &smbus_algorithm;
+ priv->adapter.dev.parent = &dev->dev;
+ ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
+ priv->adapter.retries = 3;
+ mutex_init(&priv->acpi_lock);
+
+ priv->pci_dev = dev;
+ switch (dev->device) {
+ case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS:
+ case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS:
+ case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS:
+ case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS:
+ case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
+ case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:
+ case PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS:
+ priv->features |= FEATURE_BLOCK_PROC;
+ priv->features |= FEATURE_I2C_BLOCK_READ;
+ priv->features |= FEATURE_IRQ;
+ priv->features |= FEATURE_SMBUS_PEC;
+ priv->features |= FEATURE_BLOCK_BUFFER;
+ priv->features |= FEATURE_TCO_SPT;
+ priv->features |= FEATURE_HOST_NOTIFY;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS:
+ case PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS:
+ case PCI_DEVICE_ID_INTEL_CDF_SMBUS:
+ case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS:
+ case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS:
+ case PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS:
+ case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS:
+ case PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS:
+ case PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS:
+ case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS:
+ case PCI_DEVICE_ID_INTEL_EBG_SMBUS:
+ case PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS:
+ priv->features |= FEATURE_BLOCK_PROC;
+ priv->features |= FEATURE_I2C_BLOCK_READ;
+ priv->features |= FEATURE_IRQ;
+ priv->features |= FEATURE_SMBUS_PEC;
+ priv->features |= FEATURE_BLOCK_BUFFER;
+ priv->features |= FEATURE_TCO_CNL;
+ priv->features |= FEATURE_HOST_NOTIFY;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0:
+ case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1:
+ case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2:
+ case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0:
+ case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1:
+ case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2:
+ priv->features |= FEATURE_IDF;
+ fallthrough;
+ default:
+ priv->features |= FEATURE_BLOCK_PROC;
+ priv->features |= FEATURE_I2C_BLOCK_READ;
+ priv->features |= FEATURE_IRQ;
+ fallthrough;
+ case PCI_DEVICE_ID_INTEL_82801DB_3:
+ priv->features |= FEATURE_SMBUS_PEC;
+ priv->features |= FEATURE_BLOCK_BUFFER;
+ fallthrough;
+ case PCI_DEVICE_ID_INTEL_82801CA_3:
+ priv->features |= FEATURE_HOST_NOTIFY;
+ fallthrough;
+ case PCI_DEVICE_ID_INTEL_82801BA_2:
+ case PCI_DEVICE_ID_INTEL_82801AB_3:
+ case PCI_DEVICE_ID_INTEL_82801AA_3:
+ break;
+ }
+
+ /* Disable features on user request */
+ for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) {
+ if (priv->features & disable_features & (1 << i))
+ dev_notice(&dev->dev, "%s disabled by user\n",
+ i801_feature_names[i]);
+ }
+ priv->features &= ~disable_features;
+
+ err = pcim_enable_device(dev);
+ if (err) {
+ dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
+ err);
+ return err;
+ }
+ pcim_pin_device(dev);
+
+ /* Determine the address of the SMBus area */
+ priv->smba = pci_resource_start(dev, SMBBAR);
+ if (!priv->smba) {
+ dev_err(&dev->dev,
+ "SMBus base address uninitialized, upgrade BIOS\n");
+ return -ENODEV;
+ }
+
+ if (i801_acpi_probe(priv))
+ return -ENODEV;
+
+ err = pcim_iomap_regions(dev, 1 << SMBBAR,
+ dev_driver_string(&dev->dev));
+ if (err) {
+ dev_err(&dev->dev,
+ "Failed to request SMBus region 0x%lx-0x%Lx\n",
+ priv->smba,
+ (unsigned long long)pci_resource_end(dev, SMBBAR));
+ i801_acpi_remove(priv);
+ return err;
+ }
+
+ pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &priv->original_hstcfg);
+ temp = i801_setup_hstcfg(priv);
+ if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN))
+ dev_info(&dev->dev, "Enabling SMBus device\n");
+
+ if (temp & SMBHSTCFG_SMB_SMI_EN) {
+ dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
+ /* Disable SMBus interrupt feature if SMBus using SMI# */
+ priv->features &= ~FEATURE_IRQ;
+ }
+ if (temp & SMBHSTCFG_SPD_WD)
+ dev_info(&dev->dev, "SPD Write Disable is set\n");
+
+ /* Clear special mode bits */
+ if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
+ outb_p(inb_p(SMBAUXCTL(priv)) &
+ ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
+
+ /* Remember original Host Notify setting */
+ if (priv->features & FEATURE_HOST_NOTIFY)
+ priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
+
+ /* Default timeout in interrupt mode: 200 ms */
+ priv->adapter.timeout = HZ / 5;
+
+ if (dev->irq == IRQ_NOTCONNECTED)
+ priv->features &= ~FEATURE_IRQ;
+
+ if (priv->features & FEATURE_IRQ) {
+ u16 pcictl, pcists;
+
+ /* Complain if an interrupt is already pending */
+ pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists);
+ if (pcists & SMBPCISTS_INTS)
+ dev_warn(&dev->dev, "An interrupt is pending!\n");
+
+ /* Check if interrupts have been disabled */
+ pci_read_config_word(priv->pci_dev, SMBPCICTL, &pcictl);
+ if (pcictl & SMBPCICTL_INTDIS) {
+ dev_info(&dev->dev, "Interrupts are disabled\n");
+ priv->features &= ~FEATURE_IRQ;
+ }
+ }
+
+ if (priv->features & FEATURE_IRQ) {
+ init_waitqueue_head(&priv->waitq);
+
+ err = devm_request_irq(&dev->dev, dev->irq, i801_isr,
+ IRQF_SHARED,
+ dev_driver_string(&dev->dev), priv);
+ if (err) {
+ dev_err(&dev->dev, "Failed to allocate irq %d: %d\n",
+ dev->irq, err);
+ priv->features &= ~FEATURE_IRQ;
+ }
+ }
+ dev_info(&dev->dev, "SMBus using %s\n",
+ priv->features & FEATURE_IRQ ? "PCI interrupt" : "polling");
+
+ i801_add_tco(priv);
+
+ snprintf(priv->adapter.name, sizeof(priv->adapter.name),
+ "SMBus I801 adapter at %04lx", priv->smba);
+ err = i2c_add_adapter(&priv->adapter);
+ if (err) {
+ i801_acpi_remove(priv);
+ return err;
+ }
+
+ i801_enable_host_notify(&priv->adapter);
+
+ i801_probe_optional_slaves(priv);
+ /* We ignore errors - multiplexing is optional */
+ i801_add_mux(priv);
+
+ pci_set_drvdata(dev, priv);
+
+ dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
+ pm_runtime_set_autosuspend_delay(&dev->dev, 1000);
+ pm_runtime_use_autosuspend(&dev->dev);
+ pm_runtime_put_autosuspend(&dev->dev);
+ pm_runtime_allow(&dev->dev);
+ dev_info(&dev->dev, "wb-i2c-i801 probe ok.\n");
+
+ return 0;
+}
+
+static void i801_remove(struct pci_dev *dev)
+{
+ struct i801_priv *priv = pci_get_drvdata(dev);
+
+ pm_runtime_forbid(&dev->dev);
+ pm_runtime_get_noresume(&dev->dev);
+
+ i801_disable_host_notify(priv);
+ i801_del_mux(priv);
+ i2c_del_adapter(&priv->adapter);
+ i801_acpi_remove(priv);
+ pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
+
+ platform_device_unregister(priv->tco_pdev);
+
+ /*
+ * do not call pci_disable_device(dev) since it can cause hard hangs on
+ * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
+ */
+}
+
+static void i801_shutdown(struct pci_dev *dev)
+{
+ struct i801_priv *priv = pci_get_drvdata(dev);
+
+ /* Restore config registers to avoid hard hang on some systems */
+ i801_disable_host_notify(priv);
+ pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int i801_suspend(struct device *dev)
+{
+ struct i801_priv *priv = dev_get_drvdata(dev);
+
+ pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg);
+ return 0;
+}
+
+static int i801_resume(struct device *dev)
+{
+ struct i801_priv *priv = dev_get_drvdata(dev);
+
+ i801_setup_hstcfg(priv);
+ i801_enable_host_notify(&priv->adapter);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume);
+
+static struct pci_driver i801_driver = {
+ .name = "wb_i801_smbus",
+ .id_table = i801_ids,
+ .probe = i801_probe,
+ .remove = i801_remove,
+ .shutdown = i801_shutdown,
+ .driver = {
+ .pm = &i801_pm_ops,
+ },
+};
+
+static int __init i2c_i801_init(void)
+{
+ if (dmi_name_in_vendors("FUJITSU"))
+ input_apanel_init();
+ return pci_register_driver(&i801_driver);
+}
+
+static void __exit i2c_i801_exit(void)
+{
+ pci_unregister_driver(&i801_driver);
+}
+
+MODULE_AUTHOR("support");
+MODULE_DESCRIPTION("I801 SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_i801_init);
+module_exit(i2c_i801_exit);
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_ismt.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_ismt.c
new file mode 100644
index 000000000000..94a3ed827209
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_ismt.c
@@ -0,0 +1,1131 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Copyright(c) 2012 Intel Corporation. All rights reserved.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Supports the SMBus Message Transport (SMT) in the Intel Atom Processor
+ * S12xx Product Family.
+ *
+ * Features supported by this driver:
+ * Hardware PEC yes
+ * Block buffer yes
+ * Block process call transaction yes
+ * Slave mode no
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+/* PCI Address Constants */
+#define SMBBAR 0
+
+#define ISMT_DBCTRL 0x388 /* ISMT PIN Control Register */
+#define ISMT_DBSTS 0X38C /* ISMT PIN Status Register */
+
+#define ISMT_DBSTS_CLK_STS (1<<9) /* bit9 SMBCLK_CUR_STS */
+#define ISMT_DBSTS_SDA_STS (1<<8) /* bit8 SMBDATA_CUR_STS */
+#define ISMT_DBCTRL_CLK_CTL (1<<1) /* bit1 SMBCLK_CTL */
+#define ISMT_DBCTRL_ENABLE (1<<31) /* bit31 EN */
+
+/* PCI DIDs for the Intel SMBus Message Transport (SMT) Devices */
+#define PCI_DEVICE_ID_INTEL_S1200_SMT0 0x0c59
+#define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a
+#define PCI_DEVICE_ID_INTEL_CDF_SMT 0x18ac
+#define PCI_DEVICE_ID_INTEL_DNV_SMT 0x19ac
+#define PCI_DEVICE_ID_INTEL_EBG_SMT 0x1bff
+#define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15
+
+#define ISMT_DESC_ENTRIES 2 /* number of descriptor entries */
+#define ISMT_MAX_RETRIES 3 /* number of SMBus retries to attempt */
+#define ISMT_LOG_ENTRIES 3 /* number of interrupt cause log entries */
+
+/* Hardware Descriptor Constants - Control Field */
+#define ISMT_DESC_CWRL 0x01 /* Command/Write Length */
+#define ISMT_DESC_BLK 0X04 /* Perform Block Transaction */
+#define ISMT_DESC_FAIR 0x08 /* Set fairness flag upon successful arbit. */
+#define ISMT_DESC_PEC 0x10 /* Packet Error Code */
+#define ISMT_DESC_I2C 0x20 /* I2C Enable */
+#define ISMT_DESC_INT 0x40 /* Interrupt */
+#define ISMT_DESC_SOE 0x80 /* Stop On Error */
+
+/* Hardware Descriptor Constants - Status Field */
+#define ISMT_DESC_SCS 0x01 /* Success */
+#define ISMT_DESC_DLTO 0x04 /* Data Low Time Out */
+#define ISMT_DESC_NAK 0x08 /* NAK Received */
+#define ISMT_DESC_CRC 0x10 /* CRC Error */
+#define ISMT_DESC_CLTO 0x20 /* Clock Low Time Out */
+#define ISMT_DESC_COL 0x40 /* Collisions */
+#define ISMT_DESC_LPR 0x80 /* Large Packet Received */
+
+/* Macros */
+#define ISMT_DESC_ADDR_RW(addr, rw) (((addr) << 1) | (rw))
+
+/* iSMT General Register address offsets (SMBBAR + ) */
+#define ISMT_GR_GCTRL 0x000 /* General Control */
+#define ISMT_GR_SMTICL 0x008 /* SMT Interrupt Cause Location */
+#define ISMT_GR_ERRINTMSK 0x010 /* Error Interrupt Mask */
+#define ISMT_GR_ERRAERMSK 0x014 /* Error AER Mask */
+#define ISMT_GR_ERRSTS 0x018 /* Error Status */
+#define ISMT_GR_ERRINFO 0x01c /* Error Information */
+
+/* iSMT Master Registers */
+#define ISMT_MSTR_MDBA 0x100 /* Master Descriptor Base Address */
+#define ISMT_MSTR_MCTRL 0x108 /* Master Control */
+#define ISMT_MSTR_MSTS 0x10c /* Master Status */
+#define ISMT_MSTR_MDS 0x110 /* Master Descriptor Size */
+#define ISMT_MSTR_RPOLICY 0x114 /* Retry Policy */
+
+/* iSMT Miscellaneous Registers */
+#define ISMT_SPGT 0x300 /* SMBus PHY Global Timing */
+
+/* General Control Register (GCTRL) bit definitions */
+#define ISMT_GCTRL_TRST 0x04 /* Target Reset */
+#define ISMT_GCTRL_KILL 0x08 /* Kill */
+#define ISMT_GCTRL_SRST 0x40 /* Soft Reset */
+
+/* Master Control Register (MCTRL) bit definitions */
+#define ISMT_MCTRL_SS 0x01 /* Start/Stop */
+#define ISMT_MCTRL_MEIE 0x10 /* Master Error Interrupt Enable */
+#define ISMT_MCTRL_FMHP 0x00ff0000 /* Firmware Master Head Ptr (FMHP) */
+
+/* Master Status Register (MSTS) bit definitions */
+#define ISMT_MSTS_HMTP 0xff0000 /* HW Master Tail Pointer (HMTP) */
+#define ISMT_MSTS_MIS 0x20 /* Master Interrupt Status (MIS) */
+#define ISMT_MSTS_MEIS 0x10 /* Master Error Int Status (MEIS) */
+#define ISMT_MSTS_IP 0x01 /* In Progress */
+
+/* Master Descriptor Size (MDS) bit definitions */
+#define ISMT_MDS_MASK 0xff /* Master Descriptor Size mask (MDS) */
+
+/* SMBus PHY Global Timing Register (SPGT) bit definitions */
+#define ISMT_SPGT_SPD_MASK 0xc0000000 /* SMBus Speed mask */
+#define ISMT_SPGT_SPD_80K 0x00 /* 80 kHz */
+#define ISMT_SPGT_SPD_100K (0x1 << 30) /* 100 kHz */
+#define ISMT_SPGT_SPD_400K (0x2U << 30) /* 400 kHz */
+#define ISMT_SPGT_SPD_1M (0x3U << 30) /* 1 MHz */
+
+
+/* MSI Control Register (MSICTL) bit definitions */
+#define ISMT_MSICTL_MSIE 0x01 /* MSI Enable */
+
+/* iSMT Hardware Descriptor */
+struct ismt_desc {
+ u8 tgtaddr_rw; /* target address & r/w bit */
+ u8 wr_len_cmd; /* write length in bytes or a command */
+ u8 rd_len; /* read length */
+ u8 control; /* control bits */
+ u8 status; /* status bits */
+ u8 retry; /* collision retry and retry count */
+ u8 rxbytes; /* received bytes */
+ u8 txbytes; /* transmitted bytes */
+ u32 dptr_low; /* lower 32 bit of the data pointer */
+ u32 dptr_high; /* upper 32 bit of the data pointer */
+} __packed;
+
+struct ismt_priv {
+ struct i2c_adapter adapter;
+ void __iomem *smba; /* PCI BAR */
+ struct pci_dev *pci_dev;
+ struct ismt_desc *hw; /* descriptor virt base addr */
+ dma_addr_t io_rng_dma; /* descriptor HW base addr */
+ u8 head; /* ring buffer head pointer */
+ struct completion cmp; /* interrupt completion */
+ u8 buffer[I2C_SMBUS_BLOCK_MAX + 16]; /* temp R/W data buffer */
+ dma_addr_t log_dma;
+ u32 *log;
+};
+
+static const struct pci_device_id ismt_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EBG_SMT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, ismt_ids);
+
+/* Bus speed control bits for slow debuggers - refer to the docs for usage */
+static unsigned int bus_speed;
+module_param(bus_speed, uint, S_IRUGO);
+MODULE_PARM_DESC(bus_speed, "Bus Speed in kHz (0 = BIOS default)");
+
+static unsigned int dma_reset_timeout = 1000;
+module_param(dma_reset_timeout, uint, S_IRUGO);
+
+static void ismt_hw_init(struct ismt_priv *priv);
+
+/**
+ * __ismt_desc_dump() - dump the contents of a specific descriptor
+ * @dev: the iSMT device
+ * @desc: the iSMT hardware descriptor
+ */
+static void __ismt_desc_dump(struct device *dev, const struct ismt_desc *desc)
+{
+
+ dev_dbg(dev, "Descriptor struct: %p\n", desc);
+ dev_dbg(dev, "\ttgtaddr_rw=0x%02X\n", desc->tgtaddr_rw);
+ dev_dbg(dev, "\twr_len_cmd=0x%02X\n", desc->wr_len_cmd);
+ dev_dbg(dev, "\trd_len= 0x%02X\n", desc->rd_len);
+ dev_dbg(dev, "\tcontrol= 0x%02X\n", desc->control);
+ dev_dbg(dev, "\tstatus= 0x%02X\n", desc->status);
+ dev_dbg(dev, "\tretry= 0x%02X\n", desc->retry);
+ dev_dbg(dev, "\trxbytes= 0x%02X\n", desc->rxbytes);
+ dev_dbg(dev, "\ttxbytes= 0x%02X\n", desc->txbytes);
+ dev_dbg(dev, "\tdptr_low= 0x%08X\n", desc->dptr_low);
+ dev_dbg(dev, "\tdptr_high= 0x%08X\n", desc->dptr_high);
+}
+/**
+ * ismt_desc_dump() - dump the contents of a descriptor for debug purposes
+ * @priv: iSMT private data
+ */
+static void ismt_desc_dump(struct ismt_priv *priv)
+{
+ struct device *dev = &priv->pci_dev->dev;
+ struct ismt_desc *desc = &priv->hw[priv->head];
+
+ dev_dbg(dev, "Dump of the descriptor struct: 0x%X\n", priv->head);
+ __ismt_desc_dump(dev, desc);
+}
+
+static void ismt_reset_dma(struct ismt_priv *priv)
+{
+ uint val;
+ u16 ctrl;
+ struct pci_dev *pdev;
+ u32 addr_lo, addr_hi;
+
+ /* save msiaddr */
+ pdev = priv->pci_dev;
+ pci_read_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_LO, &addr_lo);
+ pci_read_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, &addr_hi);
+
+ /* Clear the start bit */
+ val = readl(priv->smba + ISMT_MSTR_MCTRL);
+ val &= ~ISMT_MCTRL_SS;
+ writel(val, priv->smba + ISMT_MSTR_MCTRL);
+
+ val = readl(priv->smba + ISMT_GR_GCTRL);
+ writel(val | ISMT_GCTRL_KILL | ISMT_GCTRL_TRST | ISMT_GCTRL_SRST, priv->smba + ISMT_GR_GCTRL);
+
+ if (dma_reset_timeout > 0) {
+ usleep_range(dma_reset_timeout, dma_reset_timeout + 1);
+ }
+
+ ismt_hw_init(priv);
+ pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_LO, addr_lo);
+ pci_write_config_dword(pdev, pdev->msi_cap + PCI_MSI_ADDRESS_HI, addr_hi);
+ /* enable msi */
+ pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &ctrl);
+ ctrl |= PCI_MSI_FLAGS_ENABLE;
+ pci_write_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, ctrl);
+}
+
+/**
+ * ismt_gen_reg_dump() - dump the iSMT General Registers
+ * @priv: iSMT private data
+ */
+static void ismt_gen_reg_dump(struct ismt_priv *priv)
+{
+ struct device *dev = &priv->pci_dev->dev;
+
+ dev_dbg(dev, "Dump of the iSMT General Registers\n");
+ dev_dbg(dev, " GCTRL.... : (0x%p)=0x%X\n",
+ priv->smba + ISMT_GR_GCTRL,
+ readl(priv->smba + ISMT_GR_GCTRL));
+ dev_dbg(dev, " SMTICL... : (0x%p)=0x%016llX\n",
+ priv->smba + ISMT_GR_SMTICL,
+ (long long unsigned int)readq(priv->smba + ISMT_GR_SMTICL));
+ dev_dbg(dev, " ERRINTMSK : (0x%p)=0x%X\n",
+ priv->smba + ISMT_GR_ERRINTMSK,
+ readl(priv->smba + ISMT_GR_ERRINTMSK));
+ dev_dbg(dev, " ERRAERMSK : (0x%p)=0x%X\n",
+ priv->smba + ISMT_GR_ERRAERMSK,
+ readl(priv->smba + ISMT_GR_ERRAERMSK));
+ dev_dbg(dev, " ERRSTS... : (0x%p)=0x%X\n",
+ priv->smba + ISMT_GR_ERRSTS,
+ readl(priv->smba + ISMT_GR_ERRSTS));
+ dev_dbg(dev, " ERRINFO.. : (0x%p)=0x%X\n",
+ priv->smba + ISMT_GR_ERRINFO,
+ readl(priv->smba + ISMT_GR_ERRINFO));
+}
+
+/**
+ * ismt_mstr_reg_dump() - dump the iSMT Master Registers
+ * @priv: iSMT private data
+ */
+static void ismt_mstr_reg_dump(struct ismt_priv *priv)
+{
+ struct device *dev = &priv->pci_dev->dev;
+
+ dev_dbg(dev, "Dump of the iSMT Master Registers\n");
+ dev_dbg(dev, " MDBA..... : (0x%p)=0x%016llX\n",
+ priv->smba + ISMT_MSTR_MDBA,
+ (long long unsigned int)readq(priv->smba + ISMT_MSTR_MDBA));
+ dev_dbg(dev, " MCTRL.... : (0x%p)=0x%X\n",
+ priv->smba + ISMT_MSTR_MCTRL,
+ readl(priv->smba + ISMT_MSTR_MCTRL));
+ dev_dbg(dev, " MSTS..... : (0x%p)=0x%X\n",
+ priv->smba + ISMT_MSTR_MSTS,
+ readl(priv->smba + ISMT_MSTR_MSTS));
+ dev_dbg(dev, " MDS...... : (0x%p)=0x%X\n",
+ priv->smba + ISMT_MSTR_MDS,
+ readl(priv->smba + ISMT_MSTR_MDS));
+ dev_dbg(dev, " RPOLICY.. : (0x%p)=0x%X\n",
+ priv->smba + ISMT_MSTR_RPOLICY,
+ readl(priv->smba + ISMT_MSTR_RPOLICY));
+ dev_dbg(dev, " SPGT..... : (0x%p)=0x%X\n",
+ priv->smba + ISMT_SPGT,
+ readl(priv->smba + ISMT_SPGT));
+}
+
+/**
+ * ismt_submit_desc() - add a descriptor to the ring
+ * @priv: iSMT private data
+ */
+static void ismt_submit_desc(struct ismt_priv *priv)
+{
+ uint fmhp;
+ uint val;
+
+ ismt_desc_dump(priv);
+ ismt_gen_reg_dump(priv);
+ ismt_mstr_reg_dump(priv);
+
+ /* Set the FMHP (Firmware Master Head Pointer)*/
+ fmhp = ((priv->head + 1) % ISMT_DESC_ENTRIES) << 16;
+ val = readl(priv->smba + ISMT_MSTR_MCTRL);
+ writel((val & ~ISMT_MCTRL_FMHP) | fmhp,
+ priv->smba + ISMT_MSTR_MCTRL);
+
+ /* Set the start bit */
+ val = readl(priv->smba + ISMT_MSTR_MCTRL);
+ writel(val | ISMT_MCTRL_SS,
+ priv->smba + ISMT_MSTR_MCTRL);
+}
+
+/**
+ * ismt_process_desc() - handle the completion of the descriptor
+ * @desc: the iSMT hardware descriptor
+ * @data: data buffer from the upper layer
+ * @priv: ismt_priv struct holding our dma buffer
+ * @size: SMBus transaction type
+ * @read_write: flag to indicate if this is a read or write
+ */
+static int ismt_process_desc(const struct ismt_desc *desc,
+ union i2c_smbus_data *data,
+ struct ismt_priv *priv, int size,
+ char read_write)
+{
+ u8 *dma_buffer = PTR_ALIGN(&priv->buffer[0], 16);
+
+ dev_dbg(&priv->pci_dev->dev, "Processing completed descriptor\n");
+ __ismt_desc_dump(&priv->pci_dev->dev, desc);
+ ismt_gen_reg_dump(priv);
+ ismt_mstr_reg_dump(priv);
+
+ if (desc->status & ISMT_DESC_SCS) {
+ if (read_write == I2C_SMBUS_WRITE &&
+ size != I2C_SMBUS_PROC_CALL &&
+ size != I2C_SMBUS_BLOCK_PROC_CALL)
+ return 0;
+
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ data->byte = dma_buffer[0];
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_PROC_CALL:
+ data->word = dma_buffer[0] | (dma_buffer[1] << 8);
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ if (desc->rxbytes != dma_buffer[0] + 1)
+ return -EMSGSIZE;
+
+ memcpy(data->block, dma_buffer, desc->rxbytes);
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ memcpy(&data->block[1], dma_buffer, desc->rxbytes);
+ data->block[0] = desc->rxbytes;
+ break;
+ }
+ return 0;
+ }
+
+ if (likely(desc->status & ISMT_DESC_NAK))
+ return -ENXIO;
+
+ if (desc->status & ISMT_DESC_CRC)
+ return -EBADMSG;
+
+ if (desc->status & ISMT_DESC_COL)
+ return -EAGAIN;
+
+ if (desc->status & ISMT_DESC_LPR)
+ return -EPROTO;
+
+ if (desc->status & (ISMT_DESC_DLTO | ISMT_DESC_CLTO))
+ return -ETIMEDOUT;
+
+ return -EIO;
+}
+
+static void ismt_setscl(struct ismt_priv *priv, unsigned int level)
+{
+ int pin_status;
+
+ pin_status = readl(priv->smba + ISMT_DBCTRL);
+ if (level == 0) {
+ pin_status &= (~ISMT_DBCTRL_CLK_CTL);
+ } else {
+ pin_status |= ISMT_DBCTRL_CLK_CTL;
+ }
+ writel(pin_status, priv->smba + ISMT_DBCTRL);
+ pin_status = readl(priv->smba + ISMT_DBCTRL);
+ dev_dbg(&priv->pci_dev->dev, "dbctrl status = 0x%04x\r\n", pin_status);
+ return;
+}
+
+static void ismt_i2c_unblock(struct ismt_priv *priv)
+{
+ int i;
+ int pin_status, ori_status;
+
+ pin_status = readl(priv->smba + ISMT_DBCTRL);
+ ori_status = pin_status;
+ if ((pin_status & ISMT_DBCTRL_ENABLE) == 0) {
+ pin_status |= ISMT_DBCTRL_ENABLE;
+ writel(pin_status, priv->smba + ISMT_DBCTRL);
+ pin_status = readl(priv->smba + ISMT_DBCTRL);
+ dev_dbg(&priv->pci_dev->dev, "enable dbctrl pin status = 0x%04x\r\n", pin_status);
+ }
+
+ for (i = 0; i < 10; i++) {
+ ismt_setscl(priv, 0);
+ udelay(5);
+ ismt_setscl(priv, 1);
+ udelay(5);
+ }
+
+ pin_status = readl(priv->smba + ISMT_DBCTRL);
+ if (pin_status != ori_status) {
+ writel(ori_status, priv->smba + ISMT_DBCTRL);
+ pin_status = readl(priv->smba + ISMT_DBCTRL);
+ dev_dbg(&priv->pci_dev->dev, "reback dbctrl pin status = 0x%04x\r\n", pin_status);
+ }
+
+ return;
+}
+
+static int ismt_check_i2c_unblock(struct ismt_priv *priv)
+{
+ int pin_status;
+
+ pin_status = readl(priv->smba + ISMT_DBSTS);
+
+ if ( (!(pin_status & ISMT_DBSTS_SDA_STS) ) && (pin_status & ISMT_DBSTS_CLK_STS) ) {
+ dev_dbg(&priv->pci_dev->dev, "SDA is low, send 9 clock to device!\n");
+ ismt_i2c_unblock(priv);
+ }
+ return 0;
+}
+
+static int ismt_check_i2c_scl(struct ismt_priv *priv)
+{
+ int pin_status;
+
+ pin_status = readl(priv->smba + ISMT_DBSTS);
+
+ if ( (pin_status & ISMT_DBSTS_SDA_STS) && (pin_status & ISMT_DBSTS_CLK_STS) ) {
+ return 0;
+ }
+
+ dev_warn(&priv->pci_dev->dev, "SDA or SCL is low.pin_status:0x%x\n", pin_status);
+ return -1;
+}
+
+/* Make sure the SMBus host is ready to start transmitting.
+ Return 0 if it is, -EIO if it is not. */
+static int ismt_check_pre(struct ismt_priv *priv)
+{
+ ismt_check_i2c_unblock(priv);
+
+ /* SDA or SCL is low, return -EIO */
+ if (ismt_check_i2c_scl(priv)) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * ismt_access() - process an SMBus command
+ * @adap: the i2c host adapter
+ * @addr: address of the i2c/SMBus target
+ * @flags: command options
+ * @read_write: read from or write to device
+ * @command: the i2c/SMBus command to issue
+ * @size: SMBus transaction type
+ * @data: read/write data buffer
+ */
+static int ismt_access(struct i2c_adapter *adap, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ int ret;
+ unsigned long time_left;
+ dma_addr_t dma_addr = 0; /* address of the data buffer */
+ u8 dma_size = 0;
+ enum dma_data_direction dma_direction = 0;
+ struct ismt_desc *desc;
+ struct ismt_priv *priv = i2c_get_adapdata(adap);
+ struct device *dev = &priv->pci_dev->dev;
+ u8 *dma_buffer = PTR_ALIGN(&priv->buffer[0], 16);
+
+ ret = ismt_check_pre(priv);
+ if (ret < 0) {
+ return ret;
+ }
+
+ desc = &priv->hw[priv->head];
+
+ /* Initialize the DMA buffer */
+ mem_clear(priv->buffer, sizeof(priv->buffer));
+
+ /* Initialize the descriptor */
+ mem_clear(desc, sizeof(struct ismt_desc));
+ desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write);
+
+ /* Always clear the log entries */
+ mem_clear(priv->log, ISMT_LOG_ENTRIES * sizeof(u32));
+
+ /* Initialize common control bits */
+ if (likely(pci_dev_msi_enabled(priv->pci_dev)))
+ desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR;
+ else
+ desc->control = ISMT_DESC_FAIR;
+
+ if ((flags & I2C_CLIENT_PEC) && (size != I2C_SMBUS_QUICK)
+ && (size != I2C_SMBUS_I2C_BLOCK_DATA))
+ desc->control |= ISMT_DESC_PEC;
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ dev_dbg(dev, "I2C_SMBUS_QUICK\n");
+ break;
+
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_WRITE) {
+ /*
+ * Send Byte
+ * The command field contains the write data
+ */
+ dev_dbg(dev, "I2C_SMBUS_BYTE: WRITE\n");
+ desc->control |= ISMT_DESC_CWRL;
+ desc->wr_len_cmd = command;
+ } else {
+ /* Receive Byte */
+ dev_dbg(dev, "I2C_SMBUS_BYTE: READ\n");
+ dma_size = 1;
+ dma_direction = DMA_FROM_DEVICE;
+ desc->rd_len = 1;
+ }
+ break;
+
+ case I2C_SMBUS_BYTE_DATA:
+ if (read_write == I2C_SMBUS_WRITE) {
+ /*
+ * Write Byte
+ * Command plus 1 data byte
+ */
+ dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: WRITE\n");
+ desc->wr_len_cmd = 2;
+ dma_size = 2;
+ dma_direction = DMA_TO_DEVICE;
+ dma_buffer[0] = command;
+ dma_buffer[1] = data->byte;
+ } else {
+ /* Read Byte */
+ dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: READ\n");
+ desc->control |= ISMT_DESC_CWRL;
+ desc->wr_len_cmd = command;
+ desc->rd_len = 1;
+ dma_size = 1;
+ dma_direction = DMA_FROM_DEVICE;
+ }
+ break;
+
+ case I2C_SMBUS_WORD_DATA:
+ if (read_write == I2C_SMBUS_WRITE) {
+ /* Write Word */
+ dev_dbg(dev, "I2C_SMBUS_WORD_DATA: WRITE\n");
+ desc->wr_len_cmd = 3;
+ dma_size = 3;
+ dma_direction = DMA_TO_DEVICE;
+ dma_buffer[0] = command;
+ dma_buffer[1] = data->word & 0xff;
+ dma_buffer[2] = data->word >> 8;
+ } else {
+ /* Read Word */
+ dev_dbg(dev, "I2C_SMBUS_WORD_DATA: READ\n");
+ desc->wr_len_cmd = command;
+ desc->control |= ISMT_DESC_CWRL;
+ desc->rd_len = 2;
+ dma_size = 2;
+ dma_direction = DMA_FROM_DEVICE;
+ }
+ break;
+
+ case I2C_SMBUS_PROC_CALL:
+ dev_dbg(dev, "I2C_SMBUS_PROC_CALL\n");
+ desc->wr_len_cmd = 3;
+ desc->rd_len = 2;
+ dma_size = 3;
+ dma_direction = DMA_BIDIRECTIONAL;
+ dma_buffer[0] = command;
+ dma_buffer[1] = data->word & 0xff;
+ dma_buffer[2] = data->word >> 8;
+ break;
+
+ case I2C_SMBUS_BLOCK_DATA:
+ if (read_write == I2C_SMBUS_WRITE) {
+ /* Block Write */
+ dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: WRITE\n");
+ if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ return -EINVAL;
+
+ dma_size = data->block[0] + 1;
+ dma_direction = DMA_TO_DEVICE;
+ desc->wr_len_cmd = dma_size;
+ desc->control |= ISMT_DESC_BLK;
+ dma_buffer[0] = command;
+ memcpy(&dma_buffer[1], &data->block[1], dma_size - 1);
+ } else {
+ /* Block Read */
+ dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n");
+ dma_size = I2C_SMBUS_BLOCK_MAX;
+ dma_direction = DMA_FROM_DEVICE;
+ desc->rd_len = dma_size;
+ desc->wr_len_cmd = command;
+ desc->control |= (ISMT_DESC_BLK | ISMT_DESC_CWRL);
+ }
+ break;
+
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ dev_dbg(dev, "I2C_SMBUS_BLOCK_PROC_CALL\n");
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ return -EINVAL;
+
+ dma_size = I2C_SMBUS_BLOCK_MAX;
+ desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 1);
+ desc->wr_len_cmd = data->block[0] + 1;
+ desc->rd_len = dma_size;
+ desc->control |= ISMT_DESC_BLK;
+ dma_direction = DMA_BIDIRECTIONAL;
+ dma_buffer[0] = command;
+ memcpy(&dma_buffer[1], &data->block[1], data->block[0]);
+ break;
+
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ /* Make sure the length is valid */
+ if (data->block[0] < 1)
+ data->block[0] = 1;
+
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
+
+ if (read_write == I2C_SMBUS_WRITE) {
+ /* i2c Block Write */
+ dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: WRITE\n");
+ dma_size = data->block[0] + 1;
+ dma_direction = DMA_TO_DEVICE;
+ desc->wr_len_cmd = dma_size;
+ desc->control |= ISMT_DESC_I2C;
+ dma_buffer[0] = command;
+ memcpy(&dma_buffer[1], &data->block[1], dma_size - 1);
+ } else {
+ /* i2c Block Read */
+ dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n");
+ dma_size = data->block[0];
+ dma_direction = DMA_FROM_DEVICE;
+ desc->rd_len = dma_size;
+ desc->wr_len_cmd = command;
+ desc->control |= (ISMT_DESC_I2C | ISMT_DESC_CWRL);
+ /*
+ * Per the "Table 15-15. I2C Commands",
+ * in the External Design Specification (EDS),
+ * (Document Number: 508084, Revision: 2.0),
+ * the _rw bit must be 0
+ */
+ desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 0);
+ }
+ break;
+
+ default:
+ dev_err(dev, "Unsupported transaction %d\n",
+ size);
+ return -EOPNOTSUPP;
+ }
+
+ /* map the data buffer */
+ if (dma_size != 0) {
+ dev_dbg(dev, " dev=%p\n", dev);
+ dev_dbg(dev, " data=%p\n", data);
+ dev_dbg(dev, " dma_buffer=%p\n", dma_buffer);
+ dev_dbg(dev, " dma_size=%d\n", dma_size);
+ dev_dbg(dev, " dma_direction=%d\n", dma_direction);
+
+ dma_addr = dma_map_single(dev,
+ dma_buffer,
+ dma_size,
+ dma_direction);
+
+ if (dma_mapping_error(dev, dma_addr)) {
+ dev_err(dev, "Error in mapping dma buffer %p\n",
+ dma_buffer);
+ return -EIO;
+ }
+
+ dev_dbg(dev, " dma_addr = %pad\n", &dma_addr);
+
+ desc->dptr_low = lower_32_bits(dma_addr);
+ desc->dptr_high = upper_32_bits(dma_addr);
+ }
+
+ reinit_completion(&priv->cmp);
+
+ /* Add the descriptor */
+ ismt_submit_desc(priv);
+
+ /* Now we wait for interrupt completion, 1s */
+ time_left = wait_for_completion_timeout(&priv->cmp, HZ*1);
+
+ /* unmap the data buffer */
+ if (dma_size != 0)
+ dma_unmap_single(dev, dma_addr, dma_size, dma_direction);
+
+ if (unlikely(!time_left)) {
+ dev_warn(dev, "completion wait timed out:addr[%d-0x%x], read_write[%d], command[0x%x], size[%d]\n",
+ adap->nr, addr, read_write, command, size);
+ ismt_reset_dma(priv);
+ ret = -ETIMEDOUT;
+ priv->head = 0;
+ return ret;
+ }
+
+ /* do any post processing of the descriptor here */
+ ret = ismt_process_desc(desc, data, priv, size, read_write);
+
+ /* Update the ring pointer */
+ priv->head++;
+ priv->head %= ISMT_DESC_ENTRIES;
+
+ return ret;
+}
+
+/**
+ * ismt_func() - report which i2c commands are supported by this adapter
+ * @adap: the i2c host adapter
+ */
+static u32 ismt_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_QUICK |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_PROC_CALL |
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ I2C_FUNC_SMBUS_BLOCK_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK |
+ I2C_FUNC_SMBUS_PEC;
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+ .smbus_xfer = ismt_access,
+ .functionality = ismt_func,
+};
+
+/**
+ * ismt_handle_isr() - interrupt handler bottom half
+ * @priv: iSMT private data
+ */
+static irqreturn_t ismt_handle_isr(struct ismt_priv *priv)
+{
+ complete(&priv->cmp);
+
+ return IRQ_HANDLED;
+}
+
+
+/**
+ * ismt_do_interrupt() - IRQ interrupt handler
+ * @vec: interrupt vector
+ * @data: iSMT private data
+ */
+static irqreturn_t ismt_do_interrupt(int vec, void *data)
+{
+ u32 val;
+ struct ismt_priv *priv = data;
+
+ /*
+ * check to see it's our interrupt, return IRQ_NONE if not ours
+ * since we are sharing interrupt
+ */
+ val = readl(priv->smba + ISMT_MSTR_MSTS);
+
+ if (!(val & (ISMT_MSTS_MIS | ISMT_MSTS_MEIS)))
+ return IRQ_NONE;
+ else
+ writel(val | ISMT_MSTS_MIS | ISMT_MSTS_MEIS,
+ priv->smba + ISMT_MSTR_MSTS);
+
+ return ismt_handle_isr(priv);
+}
+
+/**
+ * ismt_do_msi_interrupt() - MSI interrupt handler
+ * @vec: interrupt vector
+ * @data: iSMT private data
+ */
+static irqreturn_t ismt_do_msi_interrupt(int vec, void *data)
+{
+ return ismt_handle_isr(data);
+}
+
+/**
+ * ismt_hw_init() - initialize the iSMT hardware
+ * @priv: iSMT private data
+ */
+static void ismt_hw_init(struct ismt_priv *priv)
+{
+ u32 val;
+ struct device *dev = &priv->pci_dev->dev;
+
+ /* initialize the Master Descriptor Base Address (MDBA) */
+ writeq(priv->io_rng_dma, priv->smba + ISMT_MSTR_MDBA);
+
+ writeq(priv->log_dma, priv->smba + ISMT_GR_SMTICL);
+
+ /* initialize the Master Control Register (MCTRL) */
+ writel(ISMT_MCTRL_MEIE, priv->smba + ISMT_MSTR_MCTRL);
+
+ /* initialize the Master Status Register (MSTS) */
+ writel(0, priv->smba + ISMT_MSTR_MSTS);
+
+ /* initialize the Master Descriptor Size (MDS) */
+ val = readl(priv->smba + ISMT_MSTR_MDS);
+ writel((val & ~ISMT_MDS_MASK) | (ISMT_DESC_ENTRIES - 1),
+ priv->smba + ISMT_MSTR_MDS);
+
+ /*
+ * Set the SMBus speed (could use this for slow HW debuggers)
+ */
+
+ val = readl(priv->smba + ISMT_SPGT);
+
+ switch (bus_speed) {
+ case 0:
+ break;
+
+ case 80:
+ dev_dbg(dev, "Setting SMBus clock to 80 kHz\n");
+ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_80K),
+ priv->smba + ISMT_SPGT);
+ break;
+
+ case 100:
+ dev_dbg(dev, "Setting SMBus clock to 100 kHz\n");
+ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_100K),
+ priv->smba + ISMT_SPGT);
+ break;
+
+ case 400:
+ dev_dbg(dev, "Setting SMBus clock to 400 kHz\n");
+ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_400K),
+ priv->smba + ISMT_SPGT);
+ break;
+
+ case 1000:
+ dev_dbg(dev, "Setting SMBus clock to 1000 kHz\n");
+ writel(((val & ~ISMT_SPGT_SPD_MASK) | ISMT_SPGT_SPD_1M),
+ priv->smba + ISMT_SPGT);
+ break;
+
+ default:
+ dev_warn(dev, "Invalid SMBus clock speed, only 0, 80, 100, 400, and 1000 are valid\n");
+ break;
+ }
+
+ val = readl(priv->smba + ISMT_SPGT);
+
+ switch (val & ISMT_SPGT_SPD_MASK) {
+ case ISMT_SPGT_SPD_80K:
+ bus_speed = 80;
+ break;
+ case ISMT_SPGT_SPD_100K:
+ bus_speed = 100;
+ break;
+ case ISMT_SPGT_SPD_400K:
+ bus_speed = 400;
+ break;
+ case ISMT_SPGT_SPD_1M:
+ bus_speed = 1000;
+ break;
+ }
+ dev_dbg(dev, "SMBus clock is running at %d kHz\n", bus_speed);
+}
+
+/**
+ * ismt_dev_init() - initialize the iSMT data structures
+ * @priv: iSMT private data
+ */
+static int ismt_dev_init(struct ismt_priv *priv)
+{
+ /* allocate memory for the descriptor */
+ priv->hw = dmam_alloc_coherent(&priv->pci_dev->dev,
+ (ISMT_DESC_ENTRIES
+ * sizeof(struct ismt_desc)),
+ &priv->io_rng_dma,
+ GFP_KERNEL);
+ if (!priv->hw)
+ return -ENOMEM;
+
+ priv->head = 0;
+ init_completion(&priv->cmp);
+
+ priv->log = dmam_alloc_coherent(&priv->pci_dev->dev,
+ ISMT_LOG_ENTRIES * sizeof(u32),
+ &priv->log_dma, GFP_KERNEL);
+ if (!priv->log)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * ismt_int_init() - initialize interrupts
+ * @priv: iSMT private data
+ */
+static int ismt_int_init(struct ismt_priv *priv)
+{
+ int err;
+
+ /* Try using MSI interrupts */
+ err = pci_enable_msi(priv->pci_dev);
+ if (err)
+ goto intx;
+
+ err = devm_request_irq(&priv->pci_dev->dev,
+ priv->pci_dev->irq,
+ ismt_do_msi_interrupt,
+ 0,
+ "ismt-msi",
+ priv);
+ if (err) {
+ pci_disable_msi(priv->pci_dev);
+ goto intx;
+ }
+
+ return 0;
+
+ /* Try using legacy interrupts */
+intx:
+ dev_warn(&priv->pci_dev->dev,
+ "Unable to use MSI interrupts, falling back to legacy\n");
+
+ err = devm_request_irq(&priv->pci_dev->dev,
+ priv->pci_dev->irq,
+ ismt_do_interrupt,
+ IRQF_SHARED,
+ "ismt-intx",
+ priv);
+ if (err) {
+ dev_err(&priv->pci_dev->dev, "no usable interrupts\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static struct pci_driver ismt_driver;
+
+/**
+ * ismt_probe() - probe for iSMT devices
+ * @pdev: PCI-Express device
+ * @id: PCI-Express device ID
+ */
+static int
+ismt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int err;
+ struct ismt_priv *priv;
+ unsigned long start, len;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ pci_set_drvdata(pdev, priv);
+
+ i2c_set_adapdata(&priv->adapter, priv);
+ priv->adapter.owner = THIS_MODULE;
+ priv->adapter.class = I2C_CLASS_HWMON;
+ priv->adapter.algo = &smbus_algorithm;
+ priv->adapter.dev.parent = &pdev->dev;
+ ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&pdev->dev));
+ priv->adapter.retries = ISMT_MAX_RETRIES;
+
+ priv->pci_dev = pdev;
+
+ err = pcim_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to enable SMBus PCI device (%d)\n",
+ err);
+ return err;
+ }
+
+ /* enable bus mastering */
+ pci_set_master(pdev);
+
+ /* Determine the address of the SMBus area */
+ start = pci_resource_start(pdev, SMBBAR);
+ len = pci_resource_len(pdev, SMBBAR);
+ if (!start || !len) {
+ dev_err(&pdev->dev,
+ "SMBus base address uninitialized, upgrade BIOS\n");
+ return -ENODEV;
+ }
+
+ snprintf(priv->adapter.name, sizeof(priv->adapter.name),
+ "SMBus iSMT adapter at %lx", start);
+
+ dev_dbg(&priv->pci_dev->dev, " start=0x%lX\n", start);
+ dev_dbg(&priv->pci_dev->dev, " len=0x%lX\n", len);
+
+ err = acpi_check_resource_conflict(&pdev->resource[SMBBAR]);
+ if (err) {
+ dev_err(&pdev->dev, "ACPI resource conflict!\n");
+ return err;
+ }
+
+ err = pci_request_region(pdev, SMBBAR, ismt_driver.name);
+ if (err) {
+ dev_err(&pdev->dev,
+ "Failed to request SMBus region 0x%lx-0x%lx\n",
+ start, start + len);
+ return err;
+ }
+
+ priv->smba = pcim_iomap(pdev, SMBBAR, len);
+ if (!priv->smba) {
+ dev_err(&pdev->dev, "Unable to ioremap SMBus BAR\n");
+ return -ENODEV;
+ }
+
+ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+ if (err) {
+ dev_err(&pdev->dev, "dma_set_mask fail\n");
+ return -ENODEV;
+ }
+
+ err = ismt_dev_init(priv);
+ if (err)
+ return err;
+
+ ismt_hw_init(priv);
+
+ err = ismt_int_init(priv);
+ if (err)
+ return err;
+
+ err = i2c_add_adapter(&priv->adapter);
+ if (err)
+ return -ENODEV;
+ dev_info(&pdev->dev, "wb-i2c-ismt probe ok.\n");
+ return 0;
+}
+
+/**
+ * ismt_remove() - release driver resources
+ * @pdev: PCI-Express device
+ */
+static void ismt_remove(struct pci_dev *pdev)
+{
+ struct ismt_priv *priv = pci_get_drvdata(pdev);
+
+ i2c_del_adapter(&priv->adapter);
+}
+
+static struct pci_driver ismt_driver = {
+ .name = "wb_ismt_smbus",
+ .id_table = ismt_ids,
+ .probe = ismt_probe,
+ .remove = ismt_remove,
+};
+
+module_pci_driver(ismt_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Bill E. Brown ");
+MODULE_DESCRIPTION("Intel SMBus Message Transport (iSMT) driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca954x.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca954x.c
new file mode 100644
index 000000000000..854675d9fa99
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca954x.c
@@ -0,0 +1,1387 @@
+/*
+ * I2C multiplexer
+ *
+ * Copyright (c) 2008-2009 Rodolfo Giometti
+ * Copyright (c) 2008-2009 Eurotech S.p.A.
+ *
+ * This module supports the PCA954x series of I2C multiplexer/switch chips
+ * made by Philips Semiconductors.
+ * This includes the:
+ * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547
+ * and PCA9548.
+ *
+ * These chips are all controlled via the I2C bus itself, and all have a
+ * single 8-bit register. The upstream "parent" bus fans out to two,
+ * four, or eight downstream busses or channels; which of these
+ * are selected is determined by the chip type and register contents. A
+ * mux can select only one sub-bus at a time; a switch can select any
+ * combination simultaneously.
+ *
+ * Based on:
+ * pca954x.c from Kumar Gala
+ * Copyright (C) 2006
+ *
+ * Based on:
+ * pca954x.c from Ken Harrenstien
+ * Copyright (C) 2004 Google, Inc. (Ken Harrenstien)
+ *
+ * Based on:
+ * i2c-virtual_cb.c from Brian Kuschak
+ * and
+ * pca9540.c from Jean Delvare .
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wb_i2c_mux_pca954x.h"
+
+#define PCA954X_MAX_NCHANS 8
+#define PCA954X_IRQ_OFFSET 4
+
+#define I2C_RETRY_TIMES 5
+#define I2C_RETRY_WAIT_TIMES 10 /*delay 10ms*/
+
+#define WIDTH_1Byte (1)
+#define WIDTH_4Byte (4)
+
+typedef struct pca9548_cfg_info_s {
+ uint32_t pca9548_base_nr;
+ uint32_t pca9548_reset_type;
+ uint32_t rst_delay_b; /* delay time before reset(us) */
+ uint32_t rst_delay; /* reset time(us) */
+ uint32_t rst_delay_a; /* delay time after reset(us) */
+ union {
+ i2c_attr_t i2c_attr;
+ gpio_attr_t gpio_attr;
+ io_attr_t io_attr;
+ file_attr_t file_attr;
+ } attr;
+ bool select_chan_check;
+ bool close_chan_force_reset;
+} pca9548_cfg_info_t;
+
+int g_pca954x_debug = 0;
+int g_pca954x_error = 0;
+
+module_param(g_pca954x_debug, int, S_IRUGO | S_IWUSR);
+module_param(g_pca954x_error, int, S_IRUGO | S_IWUSR);
+
+#define PCA954X_DEBUG(fmt, args...) do { \
+ if (g_pca954x_debug) { \
+ printk(KERN_INFO "[PCA95x][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define PCA954X_ERROR(fmt, args...) do { \
+ if (g_pca954x_error) { \
+ printk(KERN_ERR "[PCA95x][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+extern int pca9641_setmuxflag(int nr, int flag);
+enum pca_type {
+ pca_9540,
+ pca_9542,
+ pca_9543,
+ pca_9544,
+ pca_9545,
+ pca_9546,
+ pca_9547,
+ pca_9548,
+};
+
+struct chip_desc {
+ u8 nchans;
+ u8 enable; /* used for muxes only */
+ u8 has_irq;
+ enum muxtype {
+ pca954x_ismux = 0,
+ pca954x_isswi
+ } muxtype;
+};
+
+struct pca954x {
+ const struct chip_desc *chip;
+ u8 last_chan; /* last register value */
+ u8 deselect;
+ struct i2c_client *client;
+ struct irq_domain *irq;
+ unsigned int irq_mask;
+ raw_spinlock_t lock;
+ pca9548_cfg_info_t pca9548_cfg_info; /* pca9548 reset cfg */
+};
+
+/* Provide specs for the PCA954x types we know about */
+static const struct chip_desc chips[] = {
+ [pca_9540] = {
+ .nchans = 2,
+ .enable = 0x4,
+ .muxtype = pca954x_ismux,
+ },
+ [pca_9542] = {
+ .nchans = 2,
+ .enable = 0x4,
+ .has_irq = 1,
+ .muxtype = pca954x_ismux,
+ },
+ [pca_9543] = {
+ .nchans = 2,
+ .has_irq = 1,
+ .muxtype = pca954x_isswi,
+ },
+ [pca_9544] = {
+ .nchans = 4,
+ .enable = 0x4,
+ .has_irq = 1,
+ .muxtype = pca954x_ismux,
+ },
+ [pca_9545] = {
+ .nchans = 4,
+ .has_irq = 1,
+ .muxtype = pca954x_isswi,
+ },
+ [pca_9546] = {
+ .nchans = 4,
+ .muxtype = pca954x_isswi,
+ },
+ [pca_9547] = {
+ .nchans = 8,
+ .enable = 0x8,
+ .muxtype = pca954x_ismux,
+ },
+ [pca_9548] = {
+ .nchans = 8,
+ .muxtype = pca954x_isswi,
+ },
+};
+
+static const struct i2c_device_id pca954x_id[] = {
+ { "wb_pca9540", pca_9540 },
+ { "wb_pca9542", pca_9542 },
+ { "wb_pca9543", pca_9543 },
+ { "wb_pca9544", pca_9544 },
+ { "wb_pca9545", pca_9545 },
+ { "wb_pca9546", pca_9546 },
+ { "wb_pca9547", pca_9547 },
+ { "wb_pca9548", pca_9548 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pca954x_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id pca954x_of_match[] = {
+ { .compatible = "nxp,wb_pca9540", .data = &chips[pca_9540] },
+ { .compatible = "nxp,wb_pca9542", .data = &chips[pca_9542] },
+ { .compatible = "nxp,wb_pca9543", .data = &chips[pca_9543] },
+ { .compatible = "nxp,wb_pca9544", .data = &chips[pca_9544] },
+ { .compatible = "nxp,wb_pca9545", .data = &chips[pca_9545] },
+ { .compatible = "nxp,wb_pca9546", .data = &chips[pca_9546] },
+ { .compatible = "nxp,wb_pca9547", .data = &chips[pca_9547] },
+ { .compatible = "nxp,wb_pca9548", .data = &chips[pca_9548] },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pca954x_of_match);
+#endif
+
+/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ for this as they will try to lock adapter a second time */
+static int pca954x_reg_write(struct i2c_adapter *adap,
+ struct i2c_client *client, u8 val)
+{
+ int ret = -ENODEV;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg;
+ char buf[1];
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = 1;
+ buf[0] = val;
+ msg.buf = buf;
+ ret = __i2c_transfer(adap, &msg, 1);
+
+ if (ret >= 0 && ret != 1)
+ ret = -EREMOTEIO;
+ } else {
+ union i2c_smbus_data data;
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_WRITE,
+ val, I2C_SMBUS_BYTE, &data);
+ }
+ return ret;
+}
+
+static int pca954x_reg_read(struct i2c_adapter *adap,
+ struct i2c_client *client, u8 *val)
+{
+ int ret = -ENODEV;
+ u8 tmp_val;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg;
+
+ msg.addr = client->addr;
+ msg.flags = I2C_M_RD;
+ msg.len = 1;
+ msg.buf = &tmp_val;
+ ret = __i2c_transfer(adap, &msg, 1);
+
+ if (ret >= 0 && ret != 1) {
+ ret = -EREMOTEIO;
+ } else {
+ *val = tmp_val;
+ }
+ } else {
+ union i2c_smbus_data data;
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_READ,
+ 0, I2C_SMBUS_BYTE, &data);
+
+ if (!ret) {
+ tmp_val = data.byte;
+ *val = tmp_val;
+ }
+ }
+
+ return ret;
+}
+
+static int pca954x_setmuxflag(struct i2c_client *client, int flag)
+{
+ int ret;
+ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
+
+ ret = pca9641_setmuxflag(adap->nr, flag);
+ return ret;
+}
+
+static int pca9548_gpio_init(gpio_attr_t *gpio_attr)
+{
+ int err;
+
+ if (gpio_attr->gpio_init) {
+ PCA954X_DEBUG("gpio%d already init, do nothing.\n", gpio_attr->gpio);
+ return 0;
+ }
+
+ PCA954X_DEBUG("gpio%d init.\n", gpio_attr->gpio);
+ err = gpio_request(gpio_attr->gpio, "pca9548_reset");
+ if (err) {
+ goto error;
+ }
+ err = gpio_direction_output(gpio_attr->gpio, gpio_attr->reset_off);
+ if (err) {
+ gpio_free(gpio_attr->gpio);
+ goto error;
+ }
+ gpio_attr->gpio_init = 1;
+ return 0;
+error:
+ PCA954X_ERROR("pca9548_gpio_init failed, ret:%d.\n", err);
+ return err;
+}
+
+static void pca9548_gpio_free(gpio_attr_t *gpio_attr)
+{
+ if (gpio_attr->gpio_init == 1) {
+ PCA954X_DEBUG("gpio%d release.\n", gpio_attr->gpio);
+ gpio_free(gpio_attr->gpio);
+ gpio_attr->gpio_init = 0;
+ }
+}
+
+static int pca954x_reset_file_read(const char *path, uint32_t pos, uint8_t *val, size_t size)
+{
+ int ret;
+ struct file *filp;
+ loff_t tmp_pos;
+
+ struct kvec iov = {
+ .iov_base = val,
+ .iov_len = min_t(size_t, size, MAX_RW_COUNT),
+ };
+ struct iov_iter iter;
+
+ filp = filp_open(path, O_RDONLY, 0);
+ if (IS_ERR(filp)) {
+ PCA954X_ERROR("read open failed errno = %ld\r\n", -PTR_ERR(filp));
+ filp = NULL;
+ goto exit;
+ }
+
+ tmp_pos = (loff_t)pos;
+ iov_iter_kvec(&iter, ITER_DEST, &iov, 1, iov.iov_len);
+ ret = vfs_iter_read(filp, &iter, &tmp_pos, 0);
+ if (ret < 0) {
+ PCA954X_ERROR("vfs_iter_read failed, path=%s, addr=0x%x, size=%ld, ret=%d\r\n", path, pos, size, ret);
+ goto exit;
+ }
+
+ filp_close(filp, NULL);
+
+ return ret;
+
+exit:
+ if (filp != NULL) {
+ filp_close(filp, NULL);
+ }
+
+ return -1;
+}
+
+static int pca954x_reset_file_write(const char *path, uint32_t pos, uint8_t *val, size_t size)
+{
+ int ret;
+ struct file *filp;
+ loff_t tmp_pos;
+
+ struct kvec iov = {
+ .iov_base = val,
+ .iov_len = min_t(size_t, size, MAX_RW_COUNT),
+ };
+ struct iov_iter iter;
+
+ filp = filp_open(path, O_RDWR, 777);
+ if (IS_ERR(filp)) {
+ PCA954X_ERROR("write open failed errno = %ld\r\n", -PTR_ERR(filp));
+ filp = NULL;
+ goto exit;
+ }
+
+ tmp_pos = (loff_t)pos;
+ iov_iter_kvec(&iter, ITER_SOURCE, &iov, 1, iov.iov_len);
+ ret = vfs_iter_write(filp, &iter, &tmp_pos, 0);
+ if (ret < 0) {
+ PCA954X_ERROR("vfs_iter_write failed, path=%s, addr=0x%x, size=%ld, ret=%d\r\n", path, pos, size, ret);
+ goto exit;
+ }
+
+ vfs_fsync(filp, 1);
+ filp_close(filp, NULL);
+
+ return ret;
+
+exit:
+ if (filp != NULL) {
+ filp_close(filp, NULL);
+ }
+
+ return -1;
+}
+
+static int pca954x_reset_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset_addr,
+ unsigned char *buf, uint32_t size)
+{
+ struct file *fp;
+ struct i2c_client client;
+ char i2c_path[32];
+ int i ,j ;
+ int rv;
+
+ rv = 0;
+ mem_clear(i2c_path, sizeof(i2c_path));
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus);
+ fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR);
+ if (IS_ERR(fp)) {
+ PCA954X_ERROR("i2c open fail.\n");
+ return -1;
+ }
+ memcpy(&client, fp->private_data, sizeof(struct i2c_client));
+ client.addr = addr;
+ for (j = 0 ;j < size ;j++) {
+ for (i = 0; i < I2C_RETRY_TIMES; i++) {
+ rv = i2c_smbus_read_byte_data(&client, (offset_addr + j));
+ if (rv < 0) {
+ PCA954X_ERROR("i2c read failed, try again.\n");
+ msleep(I2C_RETRY_WAIT_TIMES);
+ if (i >= (I2C_RETRY_TIMES - 1)) {
+ goto out;
+ }
+ continue;
+ }
+ *(buf + j) = (unsigned char)rv;
+ break;
+ }
+ }
+out:
+ filp_close(fp, NULL);
+ return rv;
+}
+
+static int pca954x_reset_i2c_write(uint32_t bus, uint32_t dev_addr, uint32_t offset_addr,
+ uint8_t write_buf)
+{
+ struct file *fp;
+ struct i2c_client client;
+ char i2c_path[32];
+ int i;
+ int rv;
+
+ rv = 0;
+ mem_clear(i2c_path, sizeof(i2c_path));
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus);
+ fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR);
+ if (IS_ERR(fp)) {
+ PCA954X_ERROR("i2c open fail.\n");
+ return -1;
+ }
+ memcpy(&client, fp->private_data, sizeof(struct i2c_client));
+ client.addr = dev_addr;
+ for (i = 0; i < I2C_RETRY_TIMES; i++) {
+ rv = i2c_smbus_write_byte_data(&client, offset_addr, write_buf);
+ if (rv < 0) {
+ PCA954X_ERROR("i2c write failed, try again.\n");
+ msleep(I2C_RETRY_WAIT_TIMES);
+ if (i >= (I2C_RETRY_TIMES - 1)) {
+ goto out;
+ }
+ continue;
+ }
+ break;
+ }
+out:
+ filp_close(fp, NULL);
+ return rv;
+}
+
+static int pca954x_do_file_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout, err;
+ struct pca954x *data;
+ pca9548_cfg_info_t *reset_cfg;
+ file_attr_t *file_attr;
+ int udelay_cnt;
+ uint8_t read_value[4], write_reset_on_value[4], write_reset_off_value[4];
+ uint8_t tmp_read8;
+ uint32_t tmp_read32, tmp_write32;
+
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9548_cfg_info;
+ file_attr = &reset_cfg->attr.file_attr;
+ ret = -1;
+
+ PCA954X_DEBUG("rst_delay_b:%u, rst_delay:%u, rst_delay_a:%u.\n",
+ reset_cfg->rst_delay_b, reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+ PCA954X_DEBUG("dev_name:%s, offset:0x%x, mask:0x%x, on:0x%x, off:0x%x, width: %u\n",
+ file_attr->dev_name, file_attr->offset, file_attr->mask,
+ file_attr->reset_on, file_attr->reset_off, file_attr->width);
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ mem_clear(read_value, sizeof(read_value));
+ mem_clear(write_reset_on_value, sizeof(write_reset_on_value));
+ mem_clear(write_reset_off_value, sizeof(write_reset_off_value));
+ err = pca954x_reset_file_read(file_attr->dev_name, file_attr->offset, read_value, file_attr->width);
+ if (err < 0) {
+ goto out;
+ }
+
+ if (file_attr->width == WIDTH_1Byte) {
+ tmp_read8 = read_value[0];
+ write_reset_on_value[0] = ((tmp_read8 & (~file_attr->mask)) | file_attr->reset_on) & 0xFF;
+ write_reset_off_value[0] = ((tmp_read8 & (~file_attr->mask)) | file_attr->reset_off) & 0xFF;
+ PCA954X_DEBUG("1 byte write reset on val[0]: 0x%x, write reset off valu[0]: 0x%x\n",
+ write_reset_on_value[0], write_reset_off_value[0]);
+ } else {
+ memcpy((uint8_t *)&tmp_read32, read_value, 4);
+ tmp_write32 = (tmp_read32 & (~file_attr->mask)) | file_attr->reset_on;
+ memcpy(write_reset_on_value, (uint8_t *)&tmp_write32, 4);
+ tmp_write32 = (tmp_read32 & (~file_attr->mask)) | file_attr->reset_off;
+ memcpy(write_reset_off_value, (uint8_t *)&tmp_write32, 4);
+ PCA954X_DEBUG("4 byte write reset on val[0]:0x%x, val[1]:0x%x, val[2]:0x%x, val[3]:0x%x",
+ write_reset_on_value[0], write_reset_on_value[1], write_reset_on_value[2], write_reset_on_value[3]);
+ PCA954X_DEBUG("4 byte write reset off val[0]:0x%x, val[1]:0x%x, val[2]:0x%x, val[3]:0x%x",
+ write_reset_off_value[0], write_reset_off_value[1], write_reset_off_value[2], write_reset_off_value[3]);
+ }
+
+ err = pca954x_reset_file_write(file_attr->dev_name, file_attr->offset, write_reset_on_value, file_attr->width);
+ if (err < 0) {
+ goto out;
+ }
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ err = pca954x_reset_file_write(file_attr->dev_name, file_attr->offset, write_reset_off_value, file_attr->width);
+ if (err < 0) {
+ goto out;
+ }
+
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ err = pca954x_reset_file_read(file_attr->dev_name, file_attr->offset, read_value, file_attr->width);
+ if (err < 0) {
+ goto out;
+ }
+ if (file_attr->width == WIDTH_1Byte) {
+ tmp_read32 = read_value[0];
+ } else {
+ memcpy((uint8_t *)&tmp_read32, read_value, 4);
+ }
+ tmp_read32 &= (file_attr->mask);
+ if (tmp_read32 == file_attr->reset_off) {
+ ret = 0;
+ PCA954X_DEBUG("pca954x_do_file_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+ if (ret < 0) {
+ PCA954X_ERROR("pca954x_do_file_reset timeout.\n");
+ }
+out:
+ if (err < 0) {
+ PCA954X_ERROR("pca954x_do_file_reset file rd/wr failed, ret:%d.\n", err);
+ }
+
+ return ret;
+}
+
+static int pca954x_do_io_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout;
+ struct pca954x *data;
+ pca9548_cfg_info_t *reset_cfg;
+ io_attr_t *io_attr;
+ u8 val;
+ int udelay_cnt;
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9548_cfg_info;
+ io_attr = &reset_cfg->attr.io_attr;
+
+ PCA954X_DEBUG("rst_delay_b:%u, rst_delay:%u, rst_delay_a:%u.\n",
+ reset_cfg->rst_delay_b, reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+ PCA954X_DEBUG("io_addr:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ io_attr->io_addr, io_attr->mask, io_attr->reset_on, io_attr->reset_off);
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ val = inb(io_attr->io_addr);
+ val &= ~(io_attr->mask);
+ val |= io_attr->reset_on;
+ outb(val, io_attr->io_addr);
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ val &= ~(io_attr->mask);
+ val |= io_attr->reset_off;
+ outb(val, io_attr->io_addr);
+
+ ret = -1;
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ val = inb(io_attr->io_addr);
+ val &= (io_attr->mask);
+ if (val == io_attr->reset_off) {
+ ret = 0;
+ PCA954X_DEBUG("pca954x_do_io_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+
+ if (ret < 0) {
+ PCA954X_ERROR("pca954x_do_io_reset timeout.\n");
+ }
+
+ return ret;
+}
+
+static int pca954x_do_gpio_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout;
+ struct pca954x *data;
+ pca9548_cfg_info_t *reset_cfg;
+ gpio_attr_t *gpio_attr;
+ u8 val;
+ int udelay_cnt;
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9548_cfg_info;
+ gpio_attr = &reset_cfg->attr.gpio_attr;
+
+ ret = pca9548_gpio_init(gpio_attr);
+ if (ret) {
+ return -1;
+ }
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ /* reset on */
+ __gpio_set_value(gpio_attr->gpio, gpio_attr->reset_on);
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ /* reset off */
+ __gpio_set_value(gpio_attr->gpio, gpio_attr->reset_off);
+ ret = -1;
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ val = __gpio_get_value(gpio_attr->gpio);
+ if (val == gpio_attr->reset_off) {
+ ret = 0;
+ PCA954X_DEBUG("pca954x_do_gpio_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+
+ if (ret < 0) {
+ PCA954X_ERROR("pca954x_do_gpio_reset timeout.\n");
+ }
+
+ pca9548_gpio_free(gpio_attr);
+ return ret;
+}
+
+static int pca954x_do_i2c_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout, err;
+ struct pca954x *data;
+ pca9548_cfg_info_t *reset_cfg;
+ i2c_attr_t *i2c_attr;
+ u8 val;
+ int udelay_cnt;
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9548_cfg_info;
+ i2c_attr = &reset_cfg->attr.i2c_attr;
+ ret = -1;
+
+ PCA954X_DEBUG("rst_delay_b:%u, rst_delay:%u, rst_delay_a:%u.\n",
+ reset_cfg->rst_delay_b, reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+ PCA954X_DEBUG("bus:0x%x, addr:0x%x, reg:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ i2c_attr->i2c_bus, i2c_attr->i2c_addr, i2c_attr->reg_offset,
+ i2c_attr->mask, i2c_attr->reset_on, i2c_attr->reset_off);
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ err = pca954x_reset_i2c_read(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+ val &= ~(i2c_attr->mask);
+ val |= i2c_attr->reset_on;
+ err = pca954x_reset_i2c_write(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, val);
+ if (err < 0) {
+ goto out;
+ }
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ val &= ~(i2c_attr->mask);
+ val |= i2c_attr->reset_off;
+ err = pca954x_reset_i2c_write(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, val);
+ if (err < 0) {
+ goto out;
+ }
+
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ err = pca954x_reset_i2c_read(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+ val &= (i2c_attr->mask);
+ if (val == i2c_attr->reset_off) {
+ ret = 0;
+ PCA954X_DEBUG("pca954x_do_i2c_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+ if (ret < 0) {
+ PCA954X_ERROR("pca954x_do_i2c_reset timeout.\n");
+ }
+out:
+ if (err < 0) {
+ PCA954X_ERROR("pca954x_do_i2c_reset i2c op failed, ret:%d.\n", err);
+ }
+ return ret;
+}
+
+static int pca954x_do_reset(struct i2c_mux_core *muxc)
+{
+ int ret;
+ struct pca954x *data;
+
+ data = i2c_mux_priv(muxc);
+ if (data->pca9548_cfg_info.pca9548_reset_type == PCA9548_RESET_NONE) {
+ ret = -1;
+ PCA954X_DEBUG("Don't need to reset.\n");
+ } else if (data->pca9548_cfg_info.pca9548_reset_type == PCA9548_RESET_I2C) {
+ ret = pca954x_do_i2c_reset(muxc);
+ } else if (data->pca9548_cfg_info.pca9548_reset_type == PCA9548_RESET_GPIO) {
+ ret = pca954x_do_gpio_reset(muxc);
+ } else if (data->pca9548_cfg_info.pca9548_reset_type == PCA9548_RESET_IO) {
+ ret = pca954x_do_io_reset(muxc);
+ } else if (data->pca9548_cfg_info.pca9548_reset_type == PCA9548_RESET_FILE) {
+ ret = pca954x_do_file_reset(muxc);
+ } else {
+ ret = -1;
+ PCA954X_ERROR("Unsupport reset type:0x%x.\n",
+ data->pca9548_cfg_info.pca9548_reset_type);
+ }
+
+ if (ret < 0) {
+ PCA954X_ERROR("pca9548_reset_ctrl failed, reset type:%u, ret:%d.\n",
+ data->pca9548_cfg_info.pca9548_reset_type, ret);
+ }
+ return ret;
+}
+
+static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca954x *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ const struct chip_desc *chip = data->chip;
+ u8 regval;
+ int ret = 0;
+ u8 read_val = 0;
+ int rv;
+
+ /* we make switches look like muxes, not sure how to be smarter */
+ if (chip->muxtype == pca954x_ismux)
+ regval = chan | chip->enable;
+ else
+ regval = 1 << chan;
+
+ /* Only select the channel if its different from the last channel */
+ if (data->last_chan != regval) {
+ pca954x_setmuxflag(client, 0);
+ ret = pca954x_reg_write(muxc->parent, client, regval);
+ data->last_chan = ret < 0 ? 0 : regval;
+ }
+
+ if (data->pca9548_cfg_info.select_chan_check) { /* check chan */
+ ret = pca954x_reg_read(muxc->parent, client, &read_val);
+ /* read failed or chan not open, reset pca9548 */
+ if ((ret < 0) || (read_val != data->last_chan)) {
+ dev_warn(&client->dev, "pca954x open channle %u failed, do reset.\n", chan);
+ PCA954X_DEBUG("ret = %d, read_val = %d, last_chan = %d.\n", ret, read_val, data->last_chan);
+ rv = pca954x_do_reset(muxc);
+ if (rv >= 0) {
+ PCA954X_DEBUG("pca954x_do_reset success, rv = %d.\n", rv);
+ } else {
+ PCA954X_DEBUG("pca954x_do_reset failed, rv = %d.\n", rv);
+ }
+ if (ret >= 0) {
+ ret = -EIO; /* chan not match, return IO error */
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca954x *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ int ret, rv;
+
+ /* Deselect active channel */
+ data->last_chan = 0;
+ if (data->pca9548_cfg_info.close_chan_force_reset) {
+ ret = pca954x_do_reset(muxc);
+ } else {
+ ret = pca954x_reg_write(muxc->parent, client, data->last_chan);
+ if (ret < 0 ) {
+ dev_warn(&client->dev, "pca954x close channel %u failed, do reset.\n", chan);
+ rv = pca954x_do_reset(muxc);
+ if (rv == 0) {
+ ret = 0;
+ }
+ }
+ }
+
+ rv = pca954x_setmuxflag(client, 1);
+ if (rv == 0) {
+ PCA954X_DEBUG("match 9641, close 9548 channel to deselect 9641.\n");
+ (void)pca954x_reg_write(muxc->parent, client, data->last_chan);
+ } else {
+ PCA954X_DEBUG("dismatch 9641, do nothing.\n");
+ }
+
+ return ret;
+
+}
+
+static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)
+{
+ struct pca954x *data = dev_id;
+ unsigned int child_irq;
+ int ret, i, handled = 0;
+
+ ret = i2c_smbus_read_byte(data->client);
+ if (ret < 0)
+ return IRQ_NONE;
+
+ for (i = 0; i < data->chip->nchans; i++) {
+ if (ret & BIT(PCA954X_IRQ_OFFSET + i)) {
+ child_irq = irq_linear_revmap(data->irq, i);
+ handle_nested_irq(child_irq);
+ handled++;
+ }
+ }
+ return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void pca954x_irq_mask(struct irq_data *idata)
+{
+ struct pca954x *data = irq_data_get_irq_chip_data(idata);
+ unsigned int pos = idata->hwirq;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&data->lock, flags);
+
+ data->irq_mask &= ~BIT(pos);
+ if (!data->irq_mask)
+ disable_irq(data->client->irq);
+
+ raw_spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static void pca954x_irq_unmask(struct irq_data *idata)
+{
+ struct pca954x *data = irq_data_get_irq_chip_data(idata);
+ unsigned int pos = idata->hwirq;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&data->lock, flags);
+
+ if (!data->irq_mask)
+ enable_irq(data->client->irq);
+ data->irq_mask |= BIT(pos);
+
+ raw_spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)
+{
+ if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW)
+ return -EINVAL;
+ return 0;
+}
+
+static struct irq_chip pca954x_irq_chip = {
+ .name = "i2c-mux-pca954x",
+ .irq_mask = pca954x_irq_mask,
+ .irq_unmask = pca954x_irq_unmask,
+ .irq_set_type = pca954x_irq_set_type,
+};
+
+static int of_pca954x_irq_setup(struct i2c_mux_core *muxc)
+{
+ struct pca954x *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ int c, err, irq;
+
+ if (!data->chip->has_irq || client->irq <= 0)
+ return 0;
+
+ raw_spin_lock_init(&data->lock);
+
+ data->irq = irq_domain_add_linear(client->dev.of_node,
+ data->chip->nchans,
+ &irq_domain_simple_ops, data);
+ if (!data->irq)
+ return -ENODEV;
+
+ for (c = 0; c < data->chip->nchans; c++) {
+ irq = irq_create_mapping(data->irq, c);
+ irq_set_chip_data(irq, data);
+ irq_set_chip_and_handler(irq, &pca954x_irq_chip,
+ handle_simple_irq);
+ }
+
+ err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL,
+ pca954x_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ "pca954x", data);
+ if (err)
+ goto err_req_irq;
+
+ disable_irq(data->client->irq);
+
+ return 0;
+err_req_irq:
+ for (c = 0; c < data->chip->nchans; c++) {
+ irq = irq_find_mapping(data->irq, c);
+ irq_dispose_mapping(irq);
+ }
+ irq_domain_remove(data->irq);
+
+ return err;
+}
+
+static int pca954x_irq_setup(struct i2c_mux_core *muxc)
+{
+ return 0;
+}
+
+static int of_pca954x_reset_data_init(struct pca954x *data)
+{
+ int err, rv;
+ struct device *dev = &data->client->dev;
+ pca9548_cfg_info_t *reset_cfg;
+
+ reset_cfg = &data->pca9548_cfg_info;
+ if (dev == NULL || dev->of_node == NULL) {
+ PCA954X_DEBUG("dev or dev->of_node is NUll, no reset.\n");
+ reset_cfg->pca9548_reset_type = PCA9548_RESET_NONE;
+ return 0;
+ }
+
+ reset_cfg->select_chan_check = of_property_read_bool(dev->of_node, "select_chan_check");
+ reset_cfg->close_chan_force_reset = of_property_read_bool(dev->of_node, "close_chan_force_reset");
+ PCA954X_DEBUG("select_chan_check:%d, close_chan_force_reset:%d.\n", reset_cfg->select_chan_check,
+ reset_cfg->close_chan_force_reset);
+
+ if (of_property_read_u32(dev->of_node, "pca9548_reset_type", &reset_cfg->pca9548_reset_type)) {
+
+ PCA954X_DEBUG("pca9548_reset_type not found, no reset.\n");
+ reset_cfg->pca9548_reset_type = PCA9548_RESET_NONE;
+ return 0;
+ }
+ err = of_property_read_u32(dev->of_node, "rst_delay_b", &reset_cfg->rst_delay_b);
+ err |= of_property_read_u32(dev->of_node, "rst_delay", &reset_cfg->rst_delay);
+ err |= of_property_read_u32(dev->of_node, "rst_delay_a", &reset_cfg->rst_delay_a);
+
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA954X_DEBUG("reset_type:0x%x, rst_delay_b:0x%x, rst_delay:0x%x, rst_delay_a:0x%x.\n",
+ reset_cfg->pca9548_reset_type, reset_cfg->rst_delay_b,
+ reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+
+ if (reset_cfg->pca9548_reset_type == PCA9548_RESET_I2C) {
+ PCA954X_DEBUG("reset by i2c.\n");
+ err = of_property_read_u32(dev->of_node, "i2c_bus", &reset_cfg->attr.i2c_attr.i2c_bus);
+ err |=of_property_read_u32(dev->of_node, "i2c_addr", &reset_cfg->attr.i2c_attr.i2c_addr);
+ err |=of_property_read_u32(dev->of_node, "reg_offset", &reset_cfg->attr.i2c_attr.reg_offset);
+ err |=of_property_read_u32(dev->of_node, "mask", &reset_cfg->attr.i2c_attr.mask);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.i2c_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.i2c_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA954X_DEBUG("bus:%u, addr:0x%x, offset:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ reset_cfg->attr.i2c_attr.i2c_bus, reset_cfg->attr.i2c_attr.i2c_addr,
+ reset_cfg->attr.i2c_attr.reg_offset, reset_cfg->attr.i2c_attr.mask,
+ reset_cfg->attr.i2c_attr.reset_on, reset_cfg->attr.i2c_attr.reset_off);
+ } else if (reset_cfg->pca9548_reset_type == PCA9548_RESET_GPIO) {
+ PCA954X_DEBUG("reset by gpio.\n");
+ err = of_property_read_u32(dev->of_node, "gpio", &reset_cfg->attr.gpio_attr.gpio);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.gpio_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.gpio_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA954X_DEBUG("gpio number:%u, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.gpio_attr.gpio, reset_cfg->attr.gpio_attr.reset_on,
+ reset_cfg->attr.gpio_attr.reset_off);
+ reset_cfg->attr.gpio_attr.gpio_init = 0;
+ } else if (reset_cfg->pca9548_reset_type == PCA9548_RESET_IO) {
+ PCA954X_DEBUG("reset by io.\n");
+ err = of_property_read_u32(dev->of_node, "io_addr", &reset_cfg->attr.io_attr.io_addr);
+ err |=of_property_read_u32(dev->of_node, "mask", &reset_cfg->attr.io_attr.mask);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.io_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.io_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA954X_DEBUG("io_addr:0x%x, mask:0x%x, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.io_attr.io_addr, reset_cfg->attr.io_attr.mask,
+ reset_cfg->attr.io_attr.reset_on, reset_cfg->attr.io_attr.reset_off);
+ } else if (reset_cfg->pca9548_reset_type == PCA9548_RESET_FILE) {
+ PCA954X_DEBUG("reset by file.\n");
+ err = of_property_read_string(dev->of_node, "dev_name", &reset_cfg->attr.file_attr.dev_name);
+ err |=of_property_read_u32(dev->of_node, "offset", &reset_cfg->attr.file_attr.offset);
+ err |=of_property_read_u32(dev->of_node, "mask", &reset_cfg->attr.file_attr.mask);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.file_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.file_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ rv = of_property_read_u32(dev->of_node, "width", &reset_cfg->attr.file_attr.width);
+ if (rv == 0) {
+ if ((reset_cfg->attr.file_attr.width != WIDTH_1Byte) && (reset_cfg->attr.file_attr.width != WIDTH_4Byte)) {
+ PCA954X_ERROR("9548 reset config error, witdh: %u not support.\n", reset_cfg->attr.file_attr.width);
+ return -EINVAL;
+ }
+ } else {
+ reset_cfg->attr.file_attr.width = 1;
+ }
+ PCA954X_DEBUG("dev_name:%s, mask:0x%x, reset_on:0x%x, reset_off:0x%x, width: %u\n",
+ reset_cfg->attr.file_attr.dev_name, reset_cfg->attr.file_attr.mask,
+ reset_cfg->attr.file_attr.reset_on, reset_cfg->attr.file_attr.reset_off, reset_cfg->attr.file_attr.width);
+ } else {
+ PCA954X_ERROR("Unsupport reset type:%d.\n", reset_cfg->pca9548_reset_type);
+ goto dts_config_err;
+ }
+ return 0;
+dts_config_err:
+ PCA954X_ERROR("dts config error, ret:%d.\n", err);
+ return -EINVAL;
+}
+
+static int pca954x_reset_data_init(struct pca954x *data)
+{
+ pca9548_cfg_info_t *reset_cfg;
+ i2c_mux_pca954x_device_t *i2c_mux_pca954x_device;
+
+ if (data->client->dev.platform_data == NULL) {
+ PCA954X_DEBUG("pca954x has no reset platform data config.\n");
+ return 0;
+ }
+ reset_cfg = &data->pca9548_cfg_info;
+ i2c_mux_pca954x_device = data->client->dev.platform_data;
+ reset_cfg->select_chan_check = i2c_mux_pca954x_device->select_chan_check;
+ reset_cfg->close_chan_force_reset = i2c_mux_pca954x_device->close_chan_force_reset;
+ PCA954X_DEBUG("select_chan_check:%d, close_chan_force_reset:%d.\n", reset_cfg->select_chan_check,
+ reset_cfg->close_chan_force_reset);
+
+ reset_cfg->pca9548_reset_type = i2c_mux_pca954x_device->pca9548_reset_type;
+ if (reset_cfg->pca9548_reset_type == PCA9548_RESET_NONE) {
+ PCA954X_DEBUG("pca9548_reset_type not found, no reset.\n");
+ return 0;
+ }
+
+ reset_cfg->rst_delay_b = i2c_mux_pca954x_device->rst_delay_b;
+ reset_cfg->rst_delay = i2c_mux_pca954x_device->rst_delay;
+ reset_cfg->rst_delay_a = i2c_mux_pca954x_device->rst_delay_a;
+ PCA954X_DEBUG("reset_type:0x%x, rst_delay_b:0x%x, rst_delay:0x%x, rst_delay_a:0x%x.\n",
+ reset_cfg->pca9548_reset_type, reset_cfg->rst_delay_b,
+ reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+
+ if (reset_cfg->pca9548_reset_type == PCA9548_RESET_I2C) {
+ PCA954X_DEBUG("reset by i2c.\n");
+ reset_cfg->attr.i2c_attr.i2c_bus = i2c_mux_pca954x_device->attr.i2c_attr.i2c_bus;
+ reset_cfg->attr.i2c_attr.i2c_addr = i2c_mux_pca954x_device->attr.i2c_attr.i2c_addr;
+ reset_cfg->attr.i2c_attr.reg_offset = i2c_mux_pca954x_device->attr.i2c_attr.reg_offset;
+ reset_cfg->attr.i2c_attr.mask = i2c_mux_pca954x_device->attr.i2c_attr.mask;
+ reset_cfg->attr.i2c_attr.reset_on = i2c_mux_pca954x_device->attr.i2c_attr.reset_on;
+ reset_cfg->attr.i2c_attr.reset_off = i2c_mux_pca954x_device->attr.i2c_attr.reset_off;
+ PCA954X_DEBUG("bus:%u, addr:0x%x, offset:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ reset_cfg->attr.i2c_attr.i2c_bus, reset_cfg->attr.i2c_attr.i2c_addr,
+ reset_cfg->attr.i2c_attr.reg_offset, reset_cfg->attr.i2c_attr.mask,
+ reset_cfg->attr.i2c_attr.reset_on, reset_cfg->attr.i2c_attr.reset_off);
+ } else if (reset_cfg->pca9548_reset_type == PCA9548_RESET_GPIO) {
+ PCA954X_DEBUG("reset by gpio.\n");
+ reset_cfg->attr.gpio_attr.gpio = i2c_mux_pca954x_device->attr.gpio_attr.gpio;
+ reset_cfg->attr.gpio_attr.reset_on = i2c_mux_pca954x_device->attr.gpio_attr.reset_on;
+ reset_cfg->attr.gpio_attr.reset_off = i2c_mux_pca954x_device->attr.gpio_attr.reset_off;
+ PCA954X_DEBUG("gpio number:%u, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.gpio_attr.gpio, reset_cfg->attr.gpio_attr.reset_on,
+ reset_cfg->attr.gpio_attr.reset_off);
+ reset_cfg->attr.gpio_attr.gpio_init = 0;
+ } else if (reset_cfg->pca9548_reset_type == PCA9548_RESET_IO) {
+ PCA954X_DEBUG("reset by io.\n");
+ reset_cfg->attr.io_attr.io_addr = i2c_mux_pca954x_device->attr.io_attr.io_addr;
+ reset_cfg->attr.io_attr.mask = i2c_mux_pca954x_device->attr.io_attr.mask;
+ reset_cfg->attr.io_attr.reset_on = i2c_mux_pca954x_device->attr.io_attr.reset_on;
+ reset_cfg->attr.io_attr.reset_off = i2c_mux_pca954x_device->attr.io_attr.reset_off;
+ PCA954X_DEBUG("io_addr:0x%x, mask:0x%x, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.io_attr.io_addr, reset_cfg->attr.io_attr.mask,
+ reset_cfg->attr.io_attr.reset_on, reset_cfg->attr.io_attr.reset_off);
+ } else if (reset_cfg->pca9548_reset_type == PCA9548_RESET_FILE) {
+ PCA954X_DEBUG("reset by file.\n");
+ reset_cfg->attr.file_attr.dev_name = i2c_mux_pca954x_device->attr.file_attr.dev_name;
+ reset_cfg->attr.file_attr.offset = i2c_mux_pca954x_device->attr.file_attr.offset;
+ reset_cfg->attr.file_attr.mask = i2c_mux_pca954x_device->attr.file_attr.mask;
+ reset_cfg->attr.file_attr.reset_on = i2c_mux_pca954x_device->attr.file_attr.reset_on;
+ reset_cfg->attr.file_attr.reset_off = i2c_mux_pca954x_device->attr.file_attr.reset_off;
+ reset_cfg->attr.file_attr.width = i2c_mux_pca954x_device->attr.file_attr.width;
+ if (reset_cfg->attr.file_attr.width > 0) {
+ if ((reset_cfg->attr.file_attr.width != WIDTH_1Byte) && (reset_cfg->attr.file_attr.width != WIDTH_4Byte)) {
+ PCA954X_ERROR("9548 reset config error, witdh: %u not support.\n", reset_cfg->attr.file_attr.width);
+ return -EINVAL;
+ }
+ } else {
+ reset_cfg->attr.file_attr.width = 1;
+ }
+ PCA954X_DEBUG("dev_name:%s, mask:0x%x, reset_on:0x%x, reset_off:0x%x, width: %u\n",
+ reset_cfg->attr.file_attr.dev_name, reset_cfg->attr.file_attr.mask,
+ reset_cfg->attr.file_attr.reset_on, reset_cfg->attr.file_attr.reset_off, reset_cfg->attr.file_attr.width);
+ } else {
+ PCA954X_ERROR("Unsupport reset type:%d.\n", reset_cfg->pca9548_reset_type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int pca954x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
+ struct device_node *of_node = client->dev.of_node;
+ bool idle_disconnect_dt;
+ struct gpio_desc *gpio;
+ int num, force, class;
+ struct i2c_mux_core *muxc;
+ struct pca954x *data;
+ const struct of_device_id *match;
+ unsigned int probe_disable;
+ int ret, dynamic_nr;
+ i2c_mux_pca954x_device_t *i2c_mux_pca954x_device;
+
+ PCA954X_DEBUG("pca954x_probe, parent bus: %d, 9548 addr:0x%x.\n", adap->nr, client->addr);
+
+ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
+ return -ENODEV;
+
+ muxc = i2c_mux_alloc(adap, &client->dev,
+ PCA954X_MAX_NCHANS, sizeof(*data), 0,
+ pca954x_select_chan, pca954x_deselect_mux);
+ if (!muxc)
+ return -ENOMEM;
+ data = i2c_mux_priv(muxc);
+
+ i2c_set_clientdata(client, muxc);
+ data->client = client;
+
+ /* Get the mux out of reset if a reset GPIO is specified. */
+ gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(gpio))
+ return PTR_ERR(gpio);
+
+ /* check device connection status */
+
+ if (client->dev.of_node == NULL) {
+ if (client->dev.platform_data == NULL) {
+ probe_disable = 1;
+ PCA954X_DEBUG("has no platform data config, set probe_disable = 1.\n");
+ } else {
+ i2c_mux_pca954x_device = client->dev.platform_data;
+ probe_disable = i2c_mux_pca954x_device->probe_disable;
+ }
+ } else {
+ probe_disable = of_property_read_bool(of_node, "probe_disable");
+ }
+
+ /* Write the mux register at addr to verify
+ * that the mux is in fact present. This also
+ * initializes the mux to disconnected state.
+ */
+ if (!probe_disable && (i2c_smbus_write_byte(client, 0) < 0)) {
+ dev_warn(&client->dev, "probe failed\n");
+ return -ENODEV;
+ }
+
+ match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
+ if (match)
+ data->chip = of_device_get_match_data(&client->dev);
+ else
+ data->chip = &chips[id->driver_data];
+
+ data->last_chan = 0; /* force the first selection */
+
+ if (client->dev.of_node == NULL) {
+ idle_disconnect_dt = false;
+ } else {
+ idle_disconnect_dt = of_node &&
+ of_property_read_bool(of_node, "i2c-mux-idle-disconnect");
+ }
+
+ if (client->dev.of_node) {
+ ret= of_pca954x_reset_data_init(data);
+ } else {
+ ret= pca954x_reset_data_init(data);
+ }
+ if (ret < 0) {
+ dev_err(&client->dev, "pca954x reset config err, ret:%d.\n", ret);
+ return ret;
+ }
+
+ if (client->dev.of_node) {
+ ret = of_pca954x_irq_setup(muxc);
+ } else {
+ ret = pca954x_irq_setup(muxc);
+ }
+ if (ret) {
+ goto fail_del_adapters;
+ }
+
+ if (client->dev.of_node == NULL) {
+ if (client->dev.platform_data == NULL) {
+ dynamic_nr = 1;
+ PCA954X_DEBUG("platform data is NULL, use dynamic adap number.\n");
+ } else {
+ i2c_mux_pca954x_device = client->dev.platform_data;
+ data->pca9548_cfg_info.pca9548_base_nr = i2c_mux_pca954x_device->pca9548_base_nr;
+ if (data->pca9548_cfg_info.pca9548_base_nr == 0) {
+ dynamic_nr = 1;
+ PCA954X_DEBUG("pca9548_base_nr = 0, use dynamic adap number.\n");
+ } else {
+ dynamic_nr = 0;
+ PCA954X_DEBUG("pca9548_base_nr:%u.\n", data->pca9548_cfg_info.pca9548_base_nr);
+ }
+ }
+ } else {
+ if (of_property_read_u32(of_node, "pca9548_base_nr", &data->pca9548_cfg_info.pca9548_base_nr)) {
+
+ dynamic_nr = 1;
+ PCA954X_DEBUG("pca9548_base_nr not found, use dynamic adap number");
+ } else {
+ dynamic_nr = 0;
+ PCA954X_DEBUG("pca9548_base_nr:%u.\n", data->pca9548_cfg_info.pca9548_base_nr);
+ }
+ }
+
+ /* Now create an adapter for each channel */
+ for (num = 0; num < data->chip->nchans; num++) {
+ bool idle_disconnect_pd = false;
+ if (dynamic_nr == 1) {
+ force = 0; /* dynamic adap number */
+ } else {
+ force = data->pca9548_cfg_info.pca9548_base_nr + num;
+ }
+
+ class = 0; /* no class by default */
+ data->deselect |= (idle_disconnect_pd ||
+ idle_disconnect_dt) << num;
+
+ ret = i2c_mux_add_adapter(muxc, force, num, class);
+ if (ret)
+ goto fail_del_adapters;
+ }
+
+ dev_info(&client->dev,
+ "registered %d multiplexed busses for I2C %s %s\n",
+ num, data->chip->muxtype == pca954x_ismux
+ ? "mux" : "switch", client->name);
+
+ return 0;
+
+fail_del_adapters:
+ i2c_mux_del_adapters(muxc);
+ return ret;
+}
+
+static void pca954x_remove(struct i2c_client *client)
+{
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct pca954x *data = i2c_mux_priv(muxc);
+ int c, irq;
+
+ if (data->irq) {
+ for (c = 0; c < data->chip->nchans; c++) {
+ irq = irq_find_mapping(data->irq, c);
+ irq_dispose_mapping(irq);
+ }
+ irq_domain_remove(data->irq);
+ }
+
+ i2c_mux_del_adapters(muxc);
+ return;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pca954x_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct pca954x *data = i2c_mux_priv(muxc);
+
+ data->last_chan = 0;
+ return i2c_smbus_write_byte(client, 0);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume);
+
+static struct i2c_driver pca954x_driver = {
+ .driver = {
+ .name = "wb_pca954x",
+ .pm = &pca954x_pm,
+ .of_match_table = of_match_ptr(pca954x_of_match),
+ },
+ .probe = pca954x_probe,
+ .remove = pca954x_remove,
+ .id_table = pca954x_id,
+};
+
+module_i2c_driver(pca954x_driver);
+
+MODULE_AUTHOR("support");
+MODULE_DESCRIPTION("PCA954x I2C mux/switch driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca954x.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca954x.h
new file mode 100644
index 000000000000..beed9b2f94ac
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca954x.h
@@ -0,0 +1,68 @@
+#ifndef __WB_I2C_MUX_PCA954X_H__
+#define __WB_I2C_MUX_PCA954X_H__
+
+#include
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+typedef enum pca9548_reset_type_s {
+ PCA9548_RESET_NONE = 0,
+ PCA9548_RESET_I2C = 1,
+ PCA9548_RESET_GPIO = 2,
+ PCA9548_RESET_IO = 3,
+ PCA9548_RESET_FILE = 4,
+} pca9548_reset_type_t;
+
+typedef struct i2c_attr_s {
+ uint32_t i2c_bus;
+ uint32_t i2c_addr;
+ uint32_t reg_offset;
+ uint32_t mask;
+ uint32_t reset_on;
+ uint32_t reset_off;
+} i2c_attr_t;
+
+typedef struct io_attr_s {
+ uint32_t io_addr;
+ uint32_t mask;
+ uint32_t reset_on;
+ uint32_t reset_off;
+} io_attr_t;
+
+typedef struct file_attr_s {
+ const char *dev_name;
+ uint32_t offset;
+ uint32_t mask;
+ uint32_t reset_on;
+ uint32_t reset_off;
+ uint32_t width;
+} file_attr_t;
+
+typedef struct gpio_attr_s {
+ int gpio_init;
+ uint32_t gpio;
+ uint32_t reset_on;
+ uint32_t reset_off;
+} gpio_attr_t;
+
+typedef struct i2c_mux_pca954x_device_s {
+ struct i2c_client *client;
+ uint32_t i2c_bus;
+ uint32_t i2c_addr;
+ uint32_t pca9548_base_nr;
+ uint32_t pca9548_reset_type;
+ uint32_t rst_delay_b; /* delay time before reset(us) */
+ uint32_t rst_delay; /* reset time(us) */
+ uint32_t rst_delay_a; /* delay time after reset(us) */
+ bool probe_disable;
+ bool select_chan_check;
+ bool close_chan_force_reset;
+ union {
+ i2c_attr_t i2c_attr;
+ gpio_attr_t gpio_attr;
+ io_attr_t io_attr;
+ file_attr_t file_attr;
+ } attr;
+} i2c_mux_pca954x_device_t;
+
+#endif
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca9641.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca9641.c
new file mode 100644
index 000000000000..a3ae9f4b2431
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca9641.c
@@ -0,0 +1,1410 @@
+/*
+ * I2C multiplexer driver for PCA9541 bus master selector
+ *
+ * Copyright (c) 2010 Ericsson AB.
+ *
+ * Author: Guenter Roeck
+ *
+ * Derived from:
+ * pca954x.c
+ *
+ * Copyright (c) 2008-2009 Rodolfo Giometti
+ * Copyright (c) 2008-2009 Eurotech S.p.A.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wb_i2c_mux_pca9641.h"
+
+/*
+ * The PCA9541 is a bus master selector. It supports two I2C masters connected
+ * to a single slave bus.
+ *
+ * Before each bus transaction, a master has to acquire bus ownership. After the
+ * transaction is complete, bus ownership has to be released. This fits well
+ * into the I2C multiplexer framework, which provides select and release
+ * functions for this purpose. For this reason, this driver is modeled as
+ * single-channel I2C bus multiplexer.
+ *
+ * This driver assumes that the two bus masters are controlled by two different
+ * hosts. If a single host controls both masters, platform code has to ensure
+ * that only one of the masters is instantiated at any given time.
+ */
+
+#define PCA9541_CONTROL 0x01
+#define PCA9541_ISTAT 0x02
+
+#define PCA9541_CTL_MYBUS (1 << 0)
+#define PCA9541_CTL_NMYBUS (1 << 1)
+#define PCA9541_CTL_BUSON (1 << 2)
+#define PCA9541_CTL_NBUSON (1 << 3)
+#define PCA9541_CTL_BUSINIT (1 << 4)
+#define PCA9541_CTL_TESTON (1 << 6)
+#define PCA9541_CTL_NTESTON (1 << 7)
+#define PCA9541_ISTAT_INTIN (1 << 0)
+#define PCA9541_ISTAT_BUSINIT (1 << 1)
+#define PCA9541_ISTAT_BUSOK (1 << 2)
+#define PCA9541_ISTAT_BUSLOST (1 << 3)
+#define PCA9541_ISTAT_MYTEST (1 << 6)
+#define PCA9541_ISTAT_NMYTEST (1 << 7)
+#define PCA9641_ID 0x00
+#define PCA9641_ID_MAGIC 0x38
+#define PCA9641_CONTROL 0x01
+#define PCA9641_STATUS 0x02
+#define PCA9641_TIME 0x03
+#define PCA9641_CTL_LOCK_REQ BIT(0)
+#define PCA9641_CTL_LOCK_GRANT BIT(1)
+#define PCA9641_CTL_BUS_CONNECT BIT(2)
+#define PCA9641_CTL_BUS_INIT BIT(3)
+#define PCA9641_CTL_SMBUS_SWRST BIT(4)
+#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5)
+#define PCA9641_CTL_SMBUS_DIS BIT(6)
+#define PCA9641_CTL_PRIORITY BIT(7)
+#define PCA9641_STS_OTHER_LOCK BIT(0)
+#define PCA9641_STS_BUS_INIT_FAIL BIT(1)
+#define PCA9641_STS_BUS_HUNG BIT(2)
+#define PCA9641_STS_MBOX_EMPTY BIT(3)
+#define PCA9641_STS_MBOX_FULL BIT(4)
+#define PCA9641_STS_TEST_INT BIT(5)
+#define PCA9641_STS_SCL_IO BIT(6)
+#define PCA9641_STS_SDA_IO BIT(7)
+#define PCA9641_RES_TIME 0x03
+#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON)
+#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS)
+#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS)
+#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON)
+#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \
+ !((y) & PCA9641_STS_OTHER_LOCK))
+#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK)
+#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT)
+
+#define PCA9641_RETRY_TIME (8)
+#define PCA9641_RESET_DELAY (150)
+
+typedef struct i2c_muxs_struct_flag
+{
+ int nr;
+ char name[48];
+ struct mutex update_lock;
+ int flag;
+}i2c_mux_flag;
+
+i2c_mux_flag pca_flag = {
+ .nr = -1,
+ .flag = -1,
+};
+
+int pca9641_setmuxflag(int nr, int flag)
+{
+ if (pca_flag.nr == nr) {
+ pca_flag.flag = flag;
+ return 0;
+ }
+ return -1;
+}
+EXPORT_SYMBOL(pca9641_setmuxflag);
+
+static int g_debug_info = 0;
+static int g_debug_err = 0;
+
+module_param(g_debug_info, int, S_IRUGO | S_IWUSR);
+module_param(g_debug_err, int, S_IRUGO | S_IWUSR);
+
+#define PCA_DEBUG(fmt, args...) do { \
+ if (g_debug_info) { \
+ printk(KERN_INFO "[pca9641][VER][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define PCA_DEBUG_ERR(fmt, args...) do { \
+ if (g_debug_err) { \
+ printk(KERN_ERR "[pca9641][ERR][func:%s line:%d]\r\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+/* arbitration timeouts, in jiffies */
+#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */
+#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */
+
+/* arbitration retry delays, in us */
+#define SELECT_DELAY_SHORT 50
+#define SELECT_DELAY_LONG 1000
+#define I2C_RETRY_TIMES (5)
+#define I2C_RETRY_WAIT_TIMES (10) /*delay 10ms*/
+
+typedef struct pca9641_cfg_info_s {
+ uint32_t pca9641_reset_type;
+ uint32_t rst_delay_b; /* delay time before reset(us) */
+ uint32_t rst_delay; /* reset time(us) */
+ uint32_t rst_delay_a; /* delay time after reset(us) */
+ union {
+ i2c_attr_t i2c_attr;
+ gpio_attr_t gpio_attr;
+ io_attr_t io_attr;
+ file_attr_t file_attr;
+ } attr;
+} pca9641_cfg_info_t;
+
+struct pca9541 {
+ struct i2c_client *client;
+ unsigned long select_timeout;
+ unsigned long arb_timeout;
+ uint32_t pca9641_nr;
+ pca9641_cfg_info_t pca9641_cfg_info; /* pca9641 reset cfg */
+};
+
+static const struct i2c_device_id pca9541_id[] = {
+ {"wb_pca9541", 0},
+ {"wb_pca9641", 1},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pca9541_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id pca9541_of_match[] = {
+ { .compatible = "nxp,wb_pca9541" },
+ { .compatible = "nxp,wb_pca9641" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pca9541_of_match);
+#endif
+
+static int pca9641_gpio_init(gpio_attr_t *gpio_attr)
+{
+ int err;
+
+ if (gpio_attr->gpio_init) {
+ PCA_DEBUG("gpio%d already init, do nothing.\n", gpio_attr->gpio);
+ return 0;
+ }
+
+ PCA_DEBUG("gpio%d init.\n", gpio_attr->gpio);
+ err = gpio_request(gpio_attr->gpio, "pca9641_reset");
+ if (err) {
+ goto error;
+ }
+ err = gpio_direction_output(gpio_attr->gpio, gpio_attr->reset_off);
+ if (err) {
+ gpio_free(gpio_attr->gpio);
+ goto error;
+ }
+ gpio_attr->gpio_init = 1;
+ return 0;
+error:
+ PCA_DEBUG_ERR("pca9641_gpio_init failed, ret:%d.\n", err);
+ return err;
+}
+
+static void pca9641_gpio_free(gpio_attr_t *gpio_attr)
+{
+ if (gpio_attr->gpio_init == 1) {
+ PCA_DEBUG("gpio%d release.\n", gpio_attr->gpio);
+ gpio_free(gpio_attr->gpio);
+ gpio_attr->gpio_init = 0;
+ }
+ return;
+}
+
+static int pca9641_reset_file_read(const char *path, uint32_t pos, uint8_t *val, size_t size)
+{
+ int ret;
+ struct file *filp;
+ loff_t tmp_pos;
+
+ struct kvec iov = {
+ .iov_base = val,
+ .iov_len = min_t(size_t, size, MAX_RW_COUNT),
+ };
+ struct iov_iter iter;
+
+ filp = filp_open(path, O_RDONLY, 0);
+ if (IS_ERR(filp)) {
+ PCA_DEBUG_ERR("read open failed errno = %ld\r\n", -PTR_ERR(filp));
+ filp = NULL;
+ goto exit;
+ }
+
+ tmp_pos = (loff_t)pos;
+ iov_iter_kvec(&iter, ITER_DEST, &iov, 1, iov.iov_len);
+ ret = vfs_iter_read(filp, &iter, &tmp_pos, 0);
+ if (ret < 0) {
+ PCA_DEBUG_ERR("vfs_iter_read failed, path=%s, addr=0x%x, size=%ld, ret=%d\r\n", path, pos, size, ret);
+ goto exit;
+ }
+
+ filp_close(filp, NULL);
+
+ return ret;
+
+exit:
+ if (filp != NULL) {
+ filp_close(filp, NULL);
+ }
+
+ return -1;
+}
+
+static int pca9641_reset_file_write(const char *path, uint32_t pos, uint8_t *val, size_t size)
+{
+ int ret;
+ struct file *filp;
+ loff_t tmp_pos;
+
+ struct kvec iov = {
+ .iov_base = val,
+ .iov_len = min_t(size_t, size, MAX_RW_COUNT),
+ };
+ struct iov_iter iter;
+
+ filp = filp_open(path, O_RDWR, 777);
+ if (IS_ERR(filp)) {
+ PCA_DEBUG_ERR("write open failed errno = %ld\r\n", -PTR_ERR(filp));
+ filp = NULL;
+ goto exit;
+ }
+
+ tmp_pos = (loff_t)pos;
+ iov_iter_kvec(&iter, ITER_SOURCE, &iov, 1, iov.iov_len);
+ ret = vfs_iter_write(filp, &iter, &tmp_pos, 0);
+ if (ret < 0) {
+ PCA_DEBUG_ERR("vfs_iter_write failed, path=%s, addr=0x%x, size=%ld, ret=%d\r\n", path, pos, size, ret);
+ goto exit;
+ }
+
+ vfs_fsync(filp, 1);
+ filp_close(filp, NULL);
+
+ return ret;
+
+exit:
+ if (filp != NULL) {
+ filp_close(filp, NULL);
+ }
+
+ return -1;
+}
+
+static int pca9641_reset_i2c_read(uint32_t bus, uint32_t addr, uint32_t offset_addr,
+ unsigned char *buf, uint32_t size)
+{
+ struct file *fp;
+ struct i2c_client client;
+ char i2c_path[32];
+ int i, j;
+ int rv;
+
+ rv = 0;
+ mem_clear(i2c_path, sizeof(i2c_path));
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus);
+ fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR);
+ if (IS_ERR(fp)) {
+ PCA_DEBUG_ERR("i2c open fail.\n");
+ return -1;
+ }
+ memcpy(&client, fp->private_data, sizeof(struct i2c_client));
+ client.addr = addr;
+ for (j = 0; j < size; j++) {
+ for (i = 0; i < I2C_RETRY_TIMES; i++) {
+ rv = i2c_smbus_read_byte_data(&client, (offset_addr + j));
+ if (rv < 0) {
+ PCA_DEBUG_ERR("i2c read failed, try again.\n");
+ msleep(I2C_RETRY_WAIT_TIMES);
+ if (i >= (I2C_RETRY_TIMES - 1)) {
+ goto out;
+ }
+ continue;
+ }
+ *(buf + j) = (unsigned char)rv;
+ break;
+ }
+ }
+out:
+ filp_close(fp, NULL);
+ return rv;
+}
+
+static int pca9641_reset_i2c_write(uint32_t bus, uint32_t dev_addr, uint32_t offset_addr,
+ uint8_t write_buf)
+{
+ struct file *fp;
+ struct i2c_client client;
+ char i2c_path[32];
+ int i;
+ int rv;
+
+ rv = 0;
+ mem_clear(i2c_path, sizeof(i2c_path));
+ snprintf(i2c_path, sizeof(i2c_path), "/dev/i2c-%d", bus);
+ fp = filp_open(i2c_path, O_RDWR, S_IRUSR | S_IWUSR);
+ if (IS_ERR(fp)) {
+ PCA_DEBUG_ERR("i2c open fail.\n");
+ return -1;
+ }
+ memcpy(&client, fp->private_data, sizeof(struct i2c_client));
+ client.addr = dev_addr;
+ for (i = 0; i < I2C_RETRY_TIMES; i++) {
+ rv = i2c_smbus_write_byte_data(&client, offset_addr, write_buf);
+ if (rv < 0) {
+ PCA_DEBUG_ERR("i2c write failed, try again.\n");
+ msleep(I2C_RETRY_WAIT_TIMES);
+ if (i >= (I2C_RETRY_TIMES - 1)) {
+ goto out;
+ }
+ continue;
+ }
+ break;
+ }
+out:
+ filp_close(fp, NULL);
+ return rv;
+}
+
+static int pca9641_do_file_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout, err;
+ struct pca9541 *data;
+ pca9641_cfg_info_t *reset_cfg;
+ file_attr_t *file_attr;
+ u8 val;
+ int udelay_cnt;
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9641_cfg_info;
+ file_attr = &reset_cfg->attr.file_attr;
+ ret = -1;
+
+ PCA_DEBUG("rst_delay_b:%u, rst_delay:%u, rst_delay_a:%u.\n",
+ reset_cfg->rst_delay_b, reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+ PCA_DEBUG("dev_name:%s, offset:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ file_attr->dev_name, file_attr->offset, file_attr->mask,
+ file_attr->reset_on, file_attr->reset_off);
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ err = pca9641_reset_file_read(file_attr->dev_name, file_attr->offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+
+ val &= ~(file_attr->mask);
+ val |= file_attr->reset_on;
+ err = pca9641_reset_file_write(file_attr->dev_name, file_attr->offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ val &= ~(file_attr->mask);
+ val |= file_attr->reset_off;
+ err = pca9641_reset_file_write(file_attr->dev_name, file_attr->offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ err = pca9641_reset_file_read(file_attr->dev_name, file_attr->offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+ val &= (file_attr->mask);
+ if (val == file_attr->reset_off) {
+ ret = 0;
+ PCA_DEBUG("pca9641_do_file_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+ if (ret < 0) {
+ PCA_DEBUG_ERR("pca9641_do_file_reset timeout.\n");
+ }
+out:
+ if (err < 0) {
+ PCA_DEBUG_ERR("pca9641_do_file_reset file rd/wr failed, ret:%d.\n", err);
+ }
+
+ return ret;
+}
+
+static int pca9641_do_io_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout;
+ struct pca9541 *data;
+ pca9641_cfg_info_t *reset_cfg;
+ io_attr_t *io_attr;
+ u8 val;
+ int udelay_cnt;
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9641_cfg_info;
+ io_attr = &reset_cfg->attr.io_attr;
+
+ PCA_DEBUG("rst_delay_b:%u, rst_delay:%u, rst_delay_a:%u.\n",
+ reset_cfg->rst_delay_b, reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+ PCA_DEBUG("io_addr:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ io_attr->io_addr, io_attr->mask, io_attr->reset_on, io_attr->reset_off);
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ val = inb(io_attr->io_addr);
+ val &= ~(io_attr->mask);
+ val |= io_attr->reset_on;
+ outb(val, io_attr->io_addr);
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ val &= ~(io_attr->mask);
+ val |= io_attr->reset_off;
+ outb(val, io_attr->io_addr);
+
+ ret = -1;
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ val = inb(io_attr->io_addr);
+ val &= (io_attr->mask);
+ if (val == io_attr->reset_off) {
+ ret = 0;
+ PCA_DEBUG("pca9641_do_io_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+
+ if (ret < 0) {
+ PCA_DEBUG_ERR("pca9641_do_io_reset timeout.\n");
+ }
+
+ return ret;
+}
+
+static int pca9641_do_gpio_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout;
+ struct pca9541 *data;
+ pca9641_cfg_info_t *reset_cfg;
+ gpio_attr_t *gpio_attr;
+ u8 val;
+ int udelay_cnt;
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9641_cfg_info;
+ gpio_attr = &reset_cfg->attr.gpio_attr;
+
+ ret = pca9641_gpio_init(gpio_attr);
+ if (ret) {
+ return -1;
+ }
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ __gpio_set_value(gpio_attr->gpio, gpio_attr->reset_on);
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ __gpio_set_value(gpio_attr->gpio, gpio_attr->reset_off);
+ ret = -1;
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ val = __gpio_get_value(gpio_attr->gpio);
+ if (val == gpio_attr->reset_off) {
+ ret = 0;
+ PCA_DEBUG("pca9641_do_gpio_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+
+ if (ret < 0) {
+ PCA_DEBUG_ERR("pca9641_do_gpio_reset timeout.\n");
+ }
+
+ pca9641_gpio_free(gpio_attr);
+ return ret;
+}
+
+static int pca9641_do_i2c_reset(struct i2c_mux_core *muxc)
+{
+ int ret, timeout, err;
+ struct pca9541 *data;
+ pca9641_cfg_info_t *reset_cfg;
+ i2c_attr_t *i2c_attr;
+ u8 val;
+ int udelay_cnt;
+
+ data = i2c_mux_priv(muxc);
+ reset_cfg = &data->pca9641_cfg_info;
+ i2c_attr = &reset_cfg->attr.i2c_attr;
+ ret = -1;
+
+ PCA_DEBUG("rst_delay_b:%u, rst_delay:%u, rst_delay_a:%u.\n",
+ reset_cfg->rst_delay_b, reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+ PCA_DEBUG("bus:0x%x, addr:0x%x, reg:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ i2c_attr->i2c_bus, i2c_attr->i2c_addr, i2c_attr->reg_offset,
+ i2c_attr->mask, i2c_attr->reset_on, i2c_attr->reset_off);
+
+ if (reset_cfg->rst_delay_b) {
+ usleep_range(reset_cfg->rst_delay_b, reset_cfg->rst_delay_b + 1);
+ }
+
+ err = pca9641_reset_i2c_read(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+
+ val &= ~(i2c_attr->mask);
+ val |= i2c_attr->reset_on;
+ err = pca9641_reset_i2c_write(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, val);
+ if (err < 0) {
+ goto out;
+ }
+
+ if (reset_cfg->rst_delay) {
+ usleep_range(reset_cfg->rst_delay, reset_cfg->rst_delay + 1);
+ }
+
+ val &= ~(i2c_attr->mask);
+ val |= i2c_attr->reset_off;
+ err = pca9641_reset_i2c_write(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, val);
+ if (err < 0) {
+ goto out;
+ }
+
+ udelay_cnt = 0;
+ timeout = reset_cfg->rst_delay_a;
+ while (timeout > 0) {
+ usleep_range(1, 2);
+ err = pca9641_reset_i2c_read(i2c_attr->i2c_bus, i2c_attr->i2c_addr,
+ i2c_attr->reg_offset, &val, sizeof(val));
+ if (err < 0) {
+ goto out;
+ }
+ val &= (i2c_attr->mask);
+ if (val == i2c_attr->reset_off) {
+ ret = 0;
+ PCA_DEBUG("pca9641_do_i2c_reset success.\n");
+ break;
+ }
+ udelay_cnt++;
+ if ((udelay_cnt % 1000) == 0) {
+ /* 1MS schedule*/
+ schedule();
+ }
+ timeout--;
+ }
+ if (ret < 0) {
+ PCA_DEBUG_ERR("pca9641_do_i2c_reset timeout.\n");
+ }
+out:
+ if (err < 0) {
+ PCA_DEBUG_ERR("pca9641_do_i2c_reset i2c op failed, ret:%d.\n", err);
+ }
+ return ret;
+}
+
+static int pca9641_do_reset(struct i2c_mux_core *muxc)
+{
+ int ret;
+ struct pca9541 *data;
+
+ data = i2c_mux_priv(muxc);
+ if (data->pca9641_cfg_info.pca9641_reset_type == PCA9641_RESET_NONE) {
+ ret = -1;
+ PCA_DEBUG("Don't need to reset.\n");
+ } else if (data->pca9641_cfg_info.pca9641_reset_type == PCA9641_RESET_I2C) {
+ ret = pca9641_do_i2c_reset(muxc);
+ } else if (data->pca9641_cfg_info.pca9641_reset_type == PCA9641_RESET_GPIO) {
+ ret = pca9641_do_gpio_reset(muxc);
+ } else if (data->pca9641_cfg_info.pca9641_reset_type == PCA9641_RESET_IO) {
+ ret = pca9641_do_io_reset(muxc);
+ } else if (data->pca9641_cfg_info.pca9641_reset_type == PCA9641_RESET_FILE) {
+ ret = pca9641_do_file_reset(muxc);
+ } else {
+ ret = -1;
+ PCA_DEBUG_ERR("Unsupport reset type:0x%x.\n",
+ data->pca9641_cfg_info.pca9641_reset_type);
+ }
+
+ if (ret < 0) {
+ PCA_DEBUG_ERR("pca9641_reset_ctrl failed, reset type:%u, ret:%d.\n",
+ data->pca9641_cfg_info.pca9641_reset_type, ret);
+ } else {
+ usleep_range(PCA9641_RESET_DELAY, PCA9641_RESET_DELAY + 1);
+ }
+ return ret;
+}
+
+/*
+ * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock the adapter a second time.
+ */
+static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int ret;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg;
+ char buf[2];
+
+ msg.addr = client->addr;
+ msg.flags = 0;
+ msg.len = 2;
+ buf[0] = command;
+ buf[1] = val;
+ msg.buf = buf;
+ ret = __i2c_transfer(adap, &msg, 1);
+ } else {
+ union i2c_smbus_data data;
+
+ data.byte = val;
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_WRITE,
+ command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ }
+
+ return ret;
+}
+
+/*
+ * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ * as they will try to lock adapter a second time.
+ */
+static int pca9541_reg_read(struct i2c_client *client, u8 command)
+{
+ struct i2c_adapter *adap = client->adapter;
+ int ret;
+ u8 val;
+
+ if (adap->algo->master_xfer) {
+ struct i2c_msg msg[2] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = &command
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &val
+ }
+ };
+ ret = __i2c_transfer(adap, msg, 2);
+ if (ret == 2)
+ ret = val;
+ else if (ret >= 0)
+ ret = -EIO;
+ } else {
+ union i2c_smbus_data data;
+
+ ret = adap->algo->smbus_xfer(adap, client->addr,
+ client->flags,
+ I2C_SMBUS_READ,
+ command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ if (!ret)
+ ret = data.byte;
+ }
+ return ret;
+}
+
+/*
+ * Arbitration management functions
+ */
+
+/* Release bus. Also reset NTESTON and BUSINIT if it was set. */
+static void pca9541_release_bus(struct i2c_client *client)
+{
+ int reg;
+
+ reg = pca9541_reg_read(client, PCA9541_CONTROL);
+ if (reg >= 0 && !busoff(reg) && mybus(reg))
+ pca9541_reg_write(client, PCA9541_CONTROL,
+ (reg & PCA9541_CTL_NBUSON) >> 1);
+}
+
+/*
+ * Arbitration is defined as a two-step process. A bus master can only activate
+ * the slave bus if it owns it; otherwise it has to request ownership first.
+ * This multi-step process ensures that access contention is resolved
+ * gracefully.
+ *
+ * Bus Ownership Other master Action
+ * state requested access
+ * ----------------------------------------------------
+ * off - yes wait for arbitration timeout or
+ * for other master to drop request
+ * off no no take ownership
+ * off yes no turn on bus
+ * on yes - done
+ * on no - wait for arbitration timeout or
+ * for other master to release bus
+ *
+ * The main contention point occurs if the slave bus is off and both masters
+ * request ownership at the same time. In this case, one master will turn on
+ * the slave bus, believing that it owns it. The other master will request
+ * bus ownership. Result is that the bus is turned on, and master which did
+ * _not_ own the slave bus before ends up owning it.
+ */
+
+/* Control commands per PCA9541 datasheet */
+static const u8 pca9541_control[16] = {
+ 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1
+};
+
+/*
+ * Channel arbitration
+ *
+ * Return values:
+ * <0: error
+ * 0 : bus not acquired
+ * 1 : bus acquired
+ */
+static int pca9541_arbitrate(struct i2c_client *client)
+{
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct pca9541 *data = i2c_mux_priv(muxc);
+ int reg;
+
+ reg = pca9541_reg_read(client, PCA9541_CONTROL);
+ if (reg < 0)
+ return reg;
+
+ if (busoff(reg)) {
+ int istat;
+ /*
+ * Bus is off. Request ownership or turn it on unless
+ * other master requested ownership.
+ */
+ istat = pca9541_reg_read(client, PCA9541_ISTAT);
+ if (!(istat & PCA9541_ISTAT_NMYTEST)
+ || time_is_before_eq_jiffies(data->arb_timeout)) {
+ /*
+ * Other master did not request ownership,
+ * or arbitration timeout expired. Take the bus.
+ */
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ pca9541_control[reg & 0x0f]
+ | PCA9541_CTL_NTESTON);
+ data->select_timeout = SELECT_DELAY_SHORT;
+ } else {
+ /*
+ * Other master requested ownership.
+ * Set extra long timeout to give it time to acquire it.
+ */
+ data->select_timeout = SELECT_DELAY_LONG * 2;
+ }
+ } else if (mybus(reg)) {
+ /*
+ * Bus is on, and we own it. We are done with acquisition.
+ * Reset NTESTON and BUSINIT, then return success.
+ */
+ if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT))
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ reg & ~(PCA9541_CTL_NTESTON
+ | PCA9541_CTL_BUSINIT));
+ return 1;
+ } else {
+ /*
+ * Other master owns the bus.
+ * If arbitration timeout has expired, force ownership.
+ * Otherwise request it.
+ */
+ data->select_timeout = SELECT_DELAY_LONG;
+ if (time_is_before_eq_jiffies(data->arb_timeout)) {
+ /* Time is up, take the bus and reset it. */
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ pca9541_control[reg & 0x0f]
+ | PCA9541_CTL_BUSINIT
+ | PCA9541_CTL_NTESTON);
+ } else {
+ /* Request bus ownership if needed */
+ if (!(reg & PCA9541_CTL_NTESTON))
+ pca9541_reg_write(client,
+ PCA9541_CONTROL,
+ reg | PCA9541_CTL_NTESTON);
+ }
+ }
+ return 0;
+}
+
+static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca9541 *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ int ret;
+ unsigned long timeout = jiffies + ARB2_TIMEOUT;
+ /* give up after this time */
+
+ data->arb_timeout = jiffies + ARB_TIMEOUT;
+ /* force bus ownership after this time */
+
+ do {
+ ret = pca9541_arbitrate(client);
+ if (ret)
+ return ret < 0 ? ret : 0;
+
+ if (data->select_timeout == SELECT_DELAY_SHORT)
+ udelay(data->select_timeout);
+ else
+ msleep(data->select_timeout / 1000);
+ } while (time_is_after_eq_jiffies(timeout));
+
+ dev_warn(&client->dev, "pca9541 select channel timeout.\n");
+ return -ETIMEDOUT;
+}
+
+static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca9541 *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ pca9541_release_bus(client);
+ return 0;
+}
+
+/*
+* Arbitration management functions
+*/
+static void pca9641_release_bus(struct i2c_client *client)
+{
+ pca9541_reg_write(client, PCA9641_CONTROL, 0x80); //master 0x80
+}
+
+/*
+* Channel arbitration
+*
+* Return values:
+* <0: error
+* 0 : bus not acquired
+* 1 : bus acquired
+*/
+static int pca9641_arbitrate(struct i2c_client *client)
+{
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct pca9541 *data = i2c_mux_priv(muxc);
+ int reg_ctl, reg_sts;
+
+ reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL);
+ if (reg_ctl < 0) {
+ PCA_DEBUG_ERR("pca9641 read control register failed, ret:%d.\n", reg_ctl);
+ return reg_ctl;
+ }
+
+ reg_sts = pca9541_reg_read(client, PCA9641_STATUS);
+ if (reg_sts < 0) {
+ PCA_DEBUG_ERR("pca9641 read status register failed, ret:%d.\n", reg_sts);
+ return reg_sts;
+ }
+
+ if (BUSOFF(reg_ctl, reg_sts)) {
+ /*
+ * Bus is off. Request ownership or turn it on unless
+ * other master requested ownership.
+ */
+ reg_ctl |= PCA9641_CTL_LOCK_REQ;
+ pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
+ reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL);
+ if (reg_ctl < 0) {
+ PCA_DEBUG_ERR("Bus is off, but read control register failed, ret:%d.\n", reg_ctl);
+ return reg_ctl;
+ }
+
+ if (lock_grant(reg_ctl)) {
+ /*
+ * Other master did not request ownership,
+ * or arbitration timeout expired. Take the bus.
+ */
+ PCA_DEBUG("Bus is off, get pca9641 arbitration success.\n");
+ reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ;
+ pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
+ return 1;
+ } else {
+ /*
+ * Other master requested ownership.
+ * Set extra long timeout to give it time to acquire it.
+ */
+ PCA_DEBUG("Bus is off, but get pca9641 arbitration failed.\n");
+ data->select_timeout = SELECT_DELAY_LONG * 2;
+ }
+ } else if (lock_grant(reg_ctl)) {
+ /*
+ * Bus is on, and we own it. We are done with acquisition.
+ */
+ PCA_DEBUG("Bus is on, get pca9641 arbitration success.\n");
+ reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ;
+ pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
+ return 1;
+ } else if (other_lock(reg_sts)) {
+ /*
+ * Other master owns the bus.
+ * If arbitration timeout has expired, force ownership.
+ * Otherwise request it.
+ */
+ PCA_DEBUG("Other master owns the bus, try to request it.\n");
+ data->select_timeout = SELECT_DELAY_LONG;
+ reg_ctl |= PCA9641_CTL_LOCK_REQ;
+ pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl);
+ }
+ return 0;
+}
+
+int pca9641_select_chan_single(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca9541 *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ int ret;
+ int result;
+ unsigned long msleep_time;
+ unsigned long timeout = jiffies + ARB2_TIMEOUT;
+ /* give up after this time */
+ data->arb_timeout = jiffies + ARB_TIMEOUT;
+ /* force bus ownership after this time */
+ for (result = 0 ; result < PCA9641_RETRY_TIME ; result ++) {
+ do {
+ ret = pca9641_arbitrate(client);
+ if (ret) {
+ return ret < 0 ? -EIO : 0;
+ }
+ msleep_time = data->select_timeout / 1000;
+ if (msleep_time < 1) {
+ msleep(1);
+ } else {
+ msleep(msleep_time);
+ }
+ } while (time_is_after_eq_jiffies(timeout));
+ timeout = jiffies + ARB2_TIMEOUT;
+ }
+ dev_warn(&client->dev, "pca9641 select channel timeout.\n");
+ return -ETIMEDOUT;
+}
+
+static int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+ int ret, rv;
+
+ ret = pca9641_select_chan_single(muxc, chan);
+ if (ret < 0) {
+ PCA_DEBUG_ERR("pca9641 select channel failed, ret:%d, try to reset pca9641.\n", ret);
+ rv = pca9641_do_reset(muxc);
+
+ if (rv < 0) {
+ PCA_DEBUG_ERR("pca9641 reset failed, rv:%d.\n", rv);
+ return ret;
+ }
+
+ ret = pca9641_select_chan_single(muxc, chan);
+ if (ret < 0) {
+ PCA_DEBUG_ERR("after pca9641 reset, select channel still failed, ret:%d.\n", ret);
+ }
+ }
+ return ret;
+}
+
+static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca9541 *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ if (pca_flag.flag) {
+ pca9641_release_bus(client);
+ }
+ return 0;
+}
+
+static int pca9641_detect_id(struct i2c_client *client)
+{
+#if 0
+ int reg;
+
+ reg = pca9541_reg_read(client, PCA9641_ID);
+ if (reg == PCA9641_ID_MAGIC)
+ return 1;
+ else
+ return 0;
+#endif
+ /* only support pca9641 */
+ return 1;
+}
+
+static int pca9641_recordflag(struct i2c_adapter *adap) {
+ if (pca_flag.flag != -1) {
+ pr_err(" %s %d has init already!!!", __func__, __LINE__);
+ return -1 ;
+ }
+ pca_flag.nr = adap->nr;
+ PCA_DEBUG(" adap->nr:%d\n", adap->nr);
+ snprintf(pca_flag.name, sizeof(pca_flag.name),adap->name);
+ return 0;
+}
+
+static int of_pca9641_reset_data_init(struct pca9541 *data)
+{
+ int err;
+ struct device *dev = &data->client->dev;
+ pca9641_cfg_info_t *reset_cfg;
+
+ reset_cfg = &data->pca9641_cfg_info;
+ if (dev == NULL || dev->of_node == NULL) {
+ PCA_DEBUG("dev or dev->of_node is NUll, no reset.\n");
+ reset_cfg->pca9641_reset_type = PCA9641_RESET_NONE;
+ return 0;
+ }
+
+ if (of_property_read_u32(dev->of_node, "pca9641_reset_type", &reset_cfg->pca9641_reset_type)) {
+
+ PCA_DEBUG("pca9641_reset_type not found, no reset.\n");
+ reset_cfg->pca9641_reset_type = PCA9641_RESET_NONE;
+ return 0;
+ }
+ err = of_property_read_u32(dev->of_node, "rst_delay_b", &reset_cfg->rst_delay_b);
+ err |= of_property_read_u32(dev->of_node, "rst_delay", &reset_cfg->rst_delay);
+ err |= of_property_read_u32(dev->of_node, "rst_delay_a", &reset_cfg->rst_delay_a);
+
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA_DEBUG("reset_type:0x%x, rst_delay_b:0x%x, rst_delay:0x%x, rst_delay_a:0x%x.\n",
+ reset_cfg->pca9641_reset_type, reset_cfg->rst_delay_b,
+ reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+
+ if (reset_cfg->pca9641_reset_type == PCA9641_RESET_I2C) {
+
+ PCA_DEBUG("reset by i2c.\n");
+ err = of_property_read_u32(dev->of_node, "i2c_bus", &reset_cfg->attr.i2c_attr.i2c_bus);
+ err |=of_property_read_u32(dev->of_node, "i2c_addr", &reset_cfg->attr.i2c_attr.i2c_addr);
+ err |=of_property_read_u32(dev->of_node, "reg_offset", &reset_cfg->attr.i2c_attr.reg_offset);
+ err |=of_property_read_u32(dev->of_node, "mask", &reset_cfg->attr.i2c_attr.mask);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.i2c_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.i2c_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA_DEBUG("bus:%u, addr:0x%x, offset:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ reset_cfg->attr.i2c_attr.i2c_bus, reset_cfg->attr.i2c_attr.i2c_addr,
+ reset_cfg->attr.i2c_attr.reg_offset, reset_cfg->attr.i2c_attr.mask,
+ reset_cfg->attr.i2c_attr.reset_on, reset_cfg->attr.i2c_attr.reset_off);
+ } else if (reset_cfg->pca9641_reset_type == PCA9641_RESET_GPIO) {
+
+ PCA_DEBUG("reset by gpio.\n");
+ err = of_property_read_u32(dev->of_node, "gpio", &reset_cfg->attr.gpio_attr.gpio);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.gpio_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.gpio_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA_DEBUG("gpio number:%u, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.gpio_attr.gpio, reset_cfg->attr.gpio_attr.reset_on,
+ reset_cfg->attr.gpio_attr.reset_off);
+ reset_cfg->attr.gpio_attr.gpio_init = 0;
+ } else if (reset_cfg->pca9641_reset_type == PCA9641_RESET_IO) {
+
+ PCA_DEBUG("reset by io.\n");
+ err = of_property_read_u32(dev->of_node, "io_addr", &reset_cfg->attr.io_attr.io_addr);
+ err |=of_property_read_u32(dev->of_node, "mask", &reset_cfg->attr.io_attr.mask);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.io_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.io_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA_DEBUG("io_addr:0x%x, mask:0x%x, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.io_attr.io_addr, reset_cfg->attr.io_attr.mask,
+ reset_cfg->attr.io_attr.reset_on, reset_cfg->attr.io_attr.reset_off);
+ } else if (reset_cfg->pca9641_reset_type == PCA9641_RESET_FILE) {
+
+ PCA_DEBUG("reset by file.\n");
+ err = of_property_read_string(dev->of_node, "dev_name", &reset_cfg->attr.file_attr.dev_name);
+ err |=of_property_read_u32(dev->of_node, "offset", &reset_cfg->attr.file_attr.offset);
+ err |=of_property_read_u32(dev->of_node, "mask", &reset_cfg->attr.file_attr.mask);
+ err |=of_property_read_u32(dev->of_node, "reset_on", &reset_cfg->attr.file_attr.reset_on);
+ err |=of_property_read_u32(dev->of_node, "reset_off", &reset_cfg->attr.file_attr.reset_off);
+ if (err) {
+ goto dts_config_err;
+ }
+ PCA_DEBUG("dev_name:%s, mask:0x%x, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.file_attr.dev_name, reset_cfg->attr.file_attr.mask,
+ reset_cfg->attr.file_attr.reset_on, reset_cfg->attr.file_attr.reset_off);
+ } else {
+ PCA_DEBUG_ERR("Unsupport reset type:%d.\n", reset_cfg->pca9641_reset_type);
+ goto dts_config_err;
+ }
+ return 0;
+dts_config_err:
+ PCA_DEBUG_ERR("dts config error, ret:%d.\n", err);
+ return -EINVAL;
+}
+
+static int pca9641_reset_data_init(struct pca9541 *data)
+{
+ pca9641_cfg_info_t *reset_cfg;
+ i2c_mux_pca9641_device_t *i2c_mux_pca9641_device;
+
+ if (data->client->dev.platform_data == NULL) {
+ PCA_DEBUG("pca9641 has no reset platform data config.\n");
+ return 0;
+ }
+ reset_cfg = &data->pca9641_cfg_info;
+ i2c_mux_pca9641_device = data->client->dev.platform_data;
+ reset_cfg->pca9641_reset_type = i2c_mux_pca9641_device->pca9641_reset_type;
+ if (reset_cfg->pca9641_reset_type == PCA9641_RESET_NONE) {
+ PCA_DEBUG("pca9641 has no reset function.\n");
+ return 0;
+ }
+
+ reset_cfg->rst_delay_b = i2c_mux_pca9641_device->rst_delay_b;
+ reset_cfg->rst_delay = i2c_mux_pca9641_device->rst_delay;
+ reset_cfg->rst_delay_a = i2c_mux_pca9641_device->rst_delay_a;
+ PCA_DEBUG("reset_type:0x%x, rst_delay_b:0x%x, rst_delay:0x%x, rst_delay_a:0x%x.\n",
+ reset_cfg->pca9641_reset_type, reset_cfg->rst_delay_b,
+ reset_cfg->rst_delay, reset_cfg->rst_delay_a);
+
+ if (reset_cfg->pca9641_reset_type == PCA9641_RESET_I2C) {
+
+ PCA_DEBUG("reset by i2c.\n");
+ reset_cfg->attr.i2c_attr.i2c_bus = i2c_mux_pca9641_device->attr.i2c_attr.i2c_bus;
+ reset_cfg->attr.i2c_attr.i2c_addr = i2c_mux_pca9641_device->attr.i2c_attr.i2c_addr;
+ reset_cfg->attr.i2c_attr.reg_offset = i2c_mux_pca9641_device->attr.i2c_attr.reg_offset;
+ reset_cfg->attr.i2c_attr.mask = i2c_mux_pca9641_device->attr.i2c_attr.mask;
+ reset_cfg->attr.i2c_attr.reset_on = i2c_mux_pca9641_device->attr.i2c_attr.reset_on;
+ reset_cfg->attr.i2c_attr.reset_off = i2c_mux_pca9641_device->attr.i2c_attr.reset_off;
+ PCA_DEBUG("bus:%u, addr:0x%x, offset:0x%x, mask:0x%x, on:0x%x, off:0x%x.\n",
+ reset_cfg->attr.i2c_attr.i2c_bus, reset_cfg->attr.i2c_attr.i2c_addr,
+ reset_cfg->attr.i2c_attr.reg_offset, reset_cfg->attr.i2c_attr.mask,
+ reset_cfg->attr.i2c_attr.reset_on, reset_cfg->attr.i2c_attr.reset_off);
+ } else if (reset_cfg->pca9641_reset_type == PCA9641_RESET_GPIO) {
+
+ PCA_DEBUG("reset by gpio.\n");
+ reset_cfg->attr.gpio_attr.gpio = i2c_mux_pca9641_device->attr.gpio_attr.gpio;
+ reset_cfg->attr.gpio_attr.reset_on = i2c_mux_pca9641_device->attr.gpio_attr.reset_on;
+ reset_cfg->attr.gpio_attr.reset_off = i2c_mux_pca9641_device->attr.gpio_attr.reset_off;
+ PCA_DEBUG("gpio number:%u, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.gpio_attr.gpio, reset_cfg->attr.gpio_attr.reset_on,
+ reset_cfg->attr.gpio_attr.reset_off);
+ reset_cfg->attr.gpio_attr.gpio_init = 0;
+ } else if (reset_cfg->pca9641_reset_type == PCA9641_RESET_IO) {
+
+ PCA_DEBUG("reset by io.\n");
+ reset_cfg->attr.io_attr.io_addr = i2c_mux_pca9641_device->attr.io_attr.io_addr;
+ reset_cfg->attr.io_attr.mask = i2c_mux_pca9641_device->attr.io_attr.mask;
+ reset_cfg->attr.io_attr.reset_on = i2c_mux_pca9641_device->attr.io_attr.reset_on;
+ reset_cfg->attr.io_attr.reset_off = i2c_mux_pca9641_device->attr.io_attr.reset_off;
+ PCA_DEBUG("io_addr:0x%x, mask:0x%x, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.io_attr.io_addr, reset_cfg->attr.io_attr.mask,
+ reset_cfg->attr.io_attr.reset_on, reset_cfg->attr.io_attr.reset_off);
+ } else if (reset_cfg->pca9641_reset_type == PCA9641_RESET_FILE) {
+
+ PCA_DEBUG("reset by file.\n");
+ reset_cfg->attr.file_attr.dev_name = i2c_mux_pca9641_device->attr.file_attr.dev_name;
+ reset_cfg->attr.file_attr.offset = i2c_mux_pca9641_device->attr.file_attr.offset;
+ reset_cfg->attr.file_attr.mask = i2c_mux_pca9641_device->attr.file_attr.mask;
+ reset_cfg->attr.file_attr.reset_on = i2c_mux_pca9641_device->attr.file_attr.reset_on;
+ reset_cfg->attr.file_attr.reset_off = i2c_mux_pca9641_device->attr.file_attr.reset_off;
+ PCA_DEBUG("dev_name:%s, mask:0x%x, reset_on:0x%x, reset_off:0x%x.\n",
+ reset_cfg->attr.file_attr.dev_name, reset_cfg->attr.file_attr.mask,
+ reset_cfg->attr.file_attr.reset_on, reset_cfg->attr.file_attr.reset_off);
+ } else {
+ PCA_DEBUG_ERR("Unsupport reset type:%d.\n", reset_cfg->pca9641_reset_type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int pca9541_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adap = client->adapter;
+ struct i2c_mux_core *muxc;
+ struct pca9541 *data;
+ int force;
+ int ret = -ENODEV;
+ int detect_id;
+ i2c_mux_pca9641_device_t *i2c_mux_pca9641_device;
+
+ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ detect_id = pca9641_detect_id(client);
+
+ /*
+ * I2C accesses are unprotected here.
+ * We have to lock the adapter before releasing the bus.
+ */
+ if (detect_id == 0) {
+ i2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
+ pca9541_release_bus(client);
+ i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
+ } else {
+ i2c_lock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
+ pca9641_release_bus(client);
+ i2c_unlock_bus(adap, I2C_LOCK_ROOT_ADAPTER);
+ }
+
+ if (detect_id == 0) { /* pca9541 */
+ muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
+ I2C_MUX_ARBITRATOR,
+ pca9541_select_chan, pca9541_release_chan);
+ if (!muxc)
+ return -ENOMEM;
+
+ data = i2c_mux_priv(muxc);
+ data->client = client;
+
+ i2c_set_clientdata(client, muxc);
+ /* Create mux adapter */
+ if (of_property_read_u32(client->dev.of_node, "pca9641_nr", &data->pca9641_nr)) {
+
+ force = 0;
+ PCA_DEBUG("pca9641_nr not found, use dynamic adap number.\n");
+ } else {
+ force = data->pca9641_nr;
+ PCA_DEBUG("pca9641_nr: %d.\n", force);
+ }
+
+ ret = i2c_mux_add_adapter(muxc, force, 0, 0);
+ if (ret)
+ return ret;
+ } else {
+ muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), I2C_MUX_ARBITRATOR,
+ pca9641_select_chan, pca9641_release_chan);
+ if (!muxc) {
+ dev_err(&client->dev, "i2c_mux_alloc failed, out of memory.\n");
+ return -ENOMEM;
+ }
+
+ data = i2c_mux_priv(muxc);
+ data->client = client;
+
+ i2c_set_clientdata(client, muxc);
+
+ if (client->dev.of_node) {
+ ret= of_pca9641_reset_data_init(data);
+ } else {
+ ret= pca9641_reset_data_init(data);
+ }
+ if (ret < 0) {
+ dev_err(&client->dev, "pca9641 reset config err, ret:%d.\n", ret);
+ return ret;
+ }
+
+ if (client->dev.of_node == NULL) {
+ if (client->dev.platform_data == NULL) {
+ force = 0;
+ PCA_DEBUG("platform data is NULL, use dynamic adap number.\n");
+ } else {
+ i2c_mux_pca9641_device = client->dev.platform_data;
+ data->pca9641_nr = i2c_mux_pca9641_device->pca9641_nr;
+ if (data->pca9641_nr == 0) {
+ force = 0;
+ PCA_DEBUG("pca9641_nr = 0, use dynamic adap number.\n");
+ } else {
+ force = data->pca9641_nr;
+ PCA_DEBUG("pca9641_nr: %d.\n", force);
+ }
+ }
+ } else {
+ /* Create mux adapter */
+ if (of_property_read_u32(client->dev.of_node, "pca9641_nr", &data->pca9641_nr)) {
+
+ force = 0;
+ PCA_DEBUG("pca9641_nr not found, use dynamic adap number.\n");
+ } else {
+ force = data->pca9641_nr;
+ PCA_DEBUG("pca9641_nr: %d.\n", force);
+ }
+ }
+
+ ret = i2c_mux_add_adapter(muxc, force, 0, 0);
+ if (ret) {
+ dev_err(&client->dev, "Failed to register master selector.\n");
+ return ret;
+ }
+ }
+ pca9641_recordflag(muxc->adapter[0]);
+
+ dev_info(&client->dev, "registered master selector for I2C %s\n", client->name);
+
+ return 0;
+}
+
+static void pca9541_remove(struct i2c_client *client)
+{
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+
+ i2c_mux_del_adapters(muxc);
+ return;
+}
+
+static struct i2c_driver pca9641_driver = {
+ .driver = {
+ .name = "wb_pca9641",
+ .of_match_table = of_match_ptr(pca9541_of_match),
+ },
+ .probe = pca9541_probe,
+ .remove = pca9541_remove,
+ .id_table = pca9541_id,
+};
+
+module_i2c_driver(pca9641_driver);
+MODULE_AUTHOR("support");
+MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
+MODULE_LICENSE("GPL v2");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca9641.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca9641.h
new file mode 100644
index 000000000000..b87f7585567b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_i2c_mux_pca9641.h
@@ -0,0 +1,64 @@
+#ifndef __WB_I2C_MUX_PCA9641_H__
+#define __WB_I2C_MUX_PCA9641_H__
+
+#include
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+typedef enum pca9641_reset_type_s {
+ PCA9641_RESET_NONE = 0,
+ PCA9641_RESET_I2C = 1,
+ PCA9641_RESET_GPIO = 2,
+ PCA9641_RESET_IO = 3,
+ PCA9641_RESET_FILE = 4,
+} pca9641_reset_type_t;
+
+typedef struct i2c_attr_s {
+ uint32_t i2c_bus;
+ uint32_t i2c_addr;
+ uint32_t reg_offset;
+ uint32_t mask;
+ uint32_t reset_on;
+ uint32_t reset_off;
+} i2c_attr_t;
+
+typedef struct io_attr_s {
+ uint32_t io_addr;
+ uint32_t mask;
+ uint32_t reset_on;
+ uint32_t reset_off;
+} io_attr_t;
+
+typedef struct file_attr_s {
+ const char *dev_name;
+ uint32_t offset;
+ uint32_t mask;
+ uint32_t reset_on;
+ uint32_t reset_off;
+} file_attr_t;
+
+typedef struct gpio_attr_s {
+ int gpio_init;
+ uint32_t gpio;
+ uint32_t reset_on;
+ uint32_t reset_off;
+} gpio_attr_t;
+
+typedef struct i2c_mux_pca9641_device_s {
+ struct i2c_client *client;
+ uint32_t i2c_bus;
+ uint32_t i2c_addr;
+ uint32_t pca9641_nr;
+ uint32_t pca9641_reset_type;
+ uint32_t rst_delay_b; /* delay time before reset(us) */
+ uint32_t rst_delay; /* reset time(us) */
+ uint32_t rst_delay_a; /* delay time after reset(us) */
+ union {
+ i2c_attr_t i2c_attr;
+ gpio_attr_t gpio_attr;
+ io_attr_t io_attr;
+ file_attr_t file_attr;
+ } attr;
+} i2c_mux_pca9641_device_t;
+
+#endif
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_ina3221.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_ina3221.c
new file mode 100644
index 000000000000..05b6da0284c0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_ina3221.c
@@ -0,0 +1,1031 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * INA3221 Triple Current/Voltage Monitor
+ *
+ * Copyright (C) 2016 Texas Instruments Incorporated - https://www.ti.com/
+ * Andrew F. Davis
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define INA3221_DRIVER_NAME "wb_ina3221"
+
+#define INA3221_CONFIG 0x00
+#define INA3221_SHUNT1 0x01
+#define INA3221_BUS1 0x02
+#define INA3221_SHUNT2 0x03
+#define INA3221_BUS2 0x04
+#define INA3221_SHUNT3 0x05
+#define INA3221_BUS3 0x06
+#define INA3221_CRIT1 0x07
+#define INA3221_WARN1 0x08
+#define INA3221_CRIT2 0x09
+#define INA3221_WARN2 0x0a
+#define INA3221_CRIT3 0x0b
+#define INA3221_WARN3 0x0c
+#define INA3221_SHUNT_SUM 0x0d
+#define INA3221_CRIT_SUM 0x0e
+#define INA3221_MASK_ENABLE 0x0f
+
+#define INA3221_CONFIG_MODE_MASK GENMASK(2, 0)
+#define INA3221_CONFIG_MODE_POWERDOWN 0
+#define INA3221_CONFIG_MODE_SHUNT BIT(0)
+#define INA3221_CONFIG_MODE_BUS BIT(1)
+#define INA3221_CONFIG_MODE_CONTINUOUS BIT(2)
+#define INA3221_CONFIG_VSH_CT_SHIFT 3
+#define INA3221_CONFIG_VSH_CT_MASK GENMASK(5, 3)
+#define INA3221_CONFIG_VSH_CT(x) (((x) & GENMASK(5, 3)) >> 3)
+#define INA3221_CONFIG_VBUS_CT_SHIFT 6
+#define INA3221_CONFIG_VBUS_CT_MASK GENMASK(8, 6)
+#define INA3221_CONFIG_VBUS_CT(x) (((x) & GENMASK(8, 6)) >> 6)
+#define INA3221_CONFIG_AVG_SHIFT 9
+#define INA3221_CONFIG_AVG_MASK GENMASK(11, 9)
+#define INA3221_CONFIG_AVG(x) (((x) & GENMASK(11, 9)) >> 9)
+#define INA3221_CONFIG_CHs_EN_MASK GENMASK(14, 12)
+#define INA3221_CONFIG_CHx_EN(x) BIT(14 - (x))
+
+#define INA3221_MASK_ENABLE_SCC_MASK GENMASK(14, 12)
+
+#define INA3221_CONFIG_DEFAULT 0x7127
+#define INA3221_RSHUNT_DEFAULT 10000
+
+enum ina3221_fields {
+ /* Configuration */
+ F_RST,
+
+ /* Status Flags */
+ F_CVRF,
+
+ /* Warning Flags */
+ F_WF3, F_WF2, F_WF1,
+
+ /* Alert Flags: SF is the summation-alert flag */
+ F_SF, F_CF3, F_CF2, F_CF1,
+
+ /* sentinel */
+ F_MAX_FIELDS
+};
+
+static const struct reg_field ina3221_reg_fields[] = {
+ [F_RST] = REG_FIELD(INA3221_CONFIG, 15, 15),
+
+ [F_CVRF] = REG_FIELD(INA3221_MASK_ENABLE, 0, 0),
+ [F_WF3] = REG_FIELD(INA3221_MASK_ENABLE, 3, 3),
+ [F_WF2] = REG_FIELD(INA3221_MASK_ENABLE, 4, 4),
+ [F_WF1] = REG_FIELD(INA3221_MASK_ENABLE, 5, 5),
+ [F_SF] = REG_FIELD(INA3221_MASK_ENABLE, 6, 6),
+ [F_CF3] = REG_FIELD(INA3221_MASK_ENABLE, 7, 7),
+ [F_CF2] = REG_FIELD(INA3221_MASK_ENABLE, 8, 8),
+ [F_CF1] = REG_FIELD(INA3221_MASK_ENABLE, 9, 9),
+};
+
+enum ina3221_channels {
+ INA3221_CHANNEL1,
+ INA3221_CHANNEL2,
+ INA3221_CHANNEL3,
+ INA3221_NUM_CHANNELS
+};
+
+/**
+ * struct ina3221_input - channel input source specific information
+ * @label: label of channel input source
+ * @shunt_resistor: shunt resistor value of channel input source
+ * @disconnected: connection status of channel input source
+ */
+struct ina3221_input {
+ const char *label;
+ int shunt_resistor;
+ bool disconnected;
+};
+
+/**
+ * struct ina3221_data - device specific information
+ * @pm_dev: Device pointer for pm runtime
+ * @regmap: Register map of the device
+ * @fields: Register fields of the device
+ * @inputs: Array of channel input source specific structures
+ * @lock: mutex lock to serialize sysfs attribute accesses
+ * @reg_config: Register value of INA3221_CONFIG
+ * @summation_shunt_resistor: equivalent shunt resistor value for summation
+ * @single_shot: running in single-shot operating mode
+ */
+struct ina3221_data {
+ struct device *pm_dev;
+ struct regmap *regmap;
+ struct regmap_field *fields[F_MAX_FIELDS];
+ struct ina3221_input inputs[INA3221_NUM_CHANNELS];
+ struct mutex lock;
+ u32 reg_config;
+ int summation_shunt_resistor;
+
+ bool single_shot;
+};
+
+static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel)
+{
+ /* Summation channel checks shunt resistor values */
+ if (channel > INA3221_CHANNEL3)
+ return ina->summation_shunt_resistor != 0;
+
+ return pm_runtime_active(ina->pm_dev) &&
+ (ina->reg_config & INA3221_CONFIG_CHx_EN(channel));
+}
+
+/**
+ * Helper function to return the resistor value for current summation.
+ *
+ * There is a condition to calculate current summation -- all the shunt
+ * resistor values should be the same, so as to simply fit the formula:
+ * current summation = shunt voltage summation / shunt resistor
+ *
+ * Returns the equivalent shunt resistor value on success or 0 on failure
+ */
+static inline int ina3221_summation_shunt_resistor(struct ina3221_data *ina)
+{
+ struct ina3221_input *input = ina->inputs;
+ int i, shunt_resistor = 0;
+
+ for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
+ if (input[i].disconnected || !input[i].shunt_resistor)
+ continue;
+ if (!shunt_resistor) {
+ /* Found the reference shunt resistor value */
+ shunt_resistor = input[i].shunt_resistor;
+ } else {
+ /* No summation if resistor values are different */
+ if (shunt_resistor != input[i].shunt_resistor)
+ return 0;
+ }
+ }
+
+ return shunt_resistor;
+}
+
+/* Lookup table for Bus and Shunt conversion times in usec */
+static const u16 ina3221_conv_time[] = {
+ 140, 204, 332, 588, 1100, 2116, 4156, 8244,
+};
+
+/* Lookup table for number of samples using in averaging mode */
+static const int ina3221_avg_samples[] = {
+ 1, 4, 16, 64, 128, 256, 512, 1024,
+};
+
+/* Converting update_interval in msec to conversion time in usec */
+static inline u32 ina3221_interval_ms_to_conv_time(u16 config, int interval)
+{
+ u32 channels = hweight16(config & INA3221_CONFIG_CHs_EN_MASK);
+ u32 samples_idx = INA3221_CONFIG_AVG(config);
+ u32 samples = ina3221_avg_samples[samples_idx];
+
+ /* Bisect the result to Bus and Shunt conversion times */
+ return DIV_ROUND_CLOSEST(interval * 1000 / 2, channels * samples);
+}
+
+/* Converting CONFIG register value to update_interval in usec */
+static inline u32 ina3221_reg_to_interval_us(u16 config)
+{
+ u32 channels = hweight16(config & INA3221_CONFIG_CHs_EN_MASK);
+ u32 vbus_ct_idx = INA3221_CONFIG_VBUS_CT(config);
+ u32 vsh_ct_idx = INA3221_CONFIG_VSH_CT(config);
+ u32 samples_idx = INA3221_CONFIG_AVG(config);
+ u32 samples = ina3221_avg_samples[samples_idx];
+ u32 vbus_ct = ina3221_conv_time[vbus_ct_idx];
+ u32 vsh_ct = ina3221_conv_time[vsh_ct_idx];
+
+ /* Calculate total conversion time */
+ return channels * (vbus_ct + vsh_ct) * samples;
+}
+
+static inline int ina3221_wait_for_data(struct ina3221_data *ina)
+{
+ u32 wait, cvrf;
+
+ wait = ina3221_reg_to_interval_us(ina->reg_config);
+
+ /* Polling the CVRF bit to make sure read data is ready */
+ return regmap_field_read_poll_timeout(ina->fields[F_CVRF],
+ cvrf, cvrf, wait, wait * 2);
+}
+
+static int ina3221_read_value(struct ina3221_data *ina, unsigned int reg,
+ int *val)
+{
+ unsigned int regval;
+ int ret;
+
+ ret = regmap_read(ina->regmap, reg, ®val);
+ if (ret)
+ return ret;
+
+ /*
+ * Shunt Voltage Sum register has 14-bit value with 1-bit shift
+ * Other Shunt Voltage registers have 12 bits with 3-bit shift
+ */
+ if (reg == INA3221_SHUNT_SUM)
+ *val = sign_extend32(regval >> 1, 14);
+ else
+ *val = sign_extend32(regval >> 3, 12);
+
+ return 0;
+}
+
+static const u8 ina3221_in_reg[] = {
+ INA3221_BUS1,
+ INA3221_BUS2,
+ INA3221_BUS3,
+ INA3221_SHUNT1,
+ INA3221_SHUNT2,
+ INA3221_SHUNT3,
+ INA3221_SHUNT_SUM,
+};
+
+static int ina3221_read_chip(struct device *dev, u32 attr, long *val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ int regval;
+
+ switch (attr) {
+ case hwmon_chip_samples:
+ regval = INA3221_CONFIG_AVG(ina->reg_config);
+ *val = ina3221_avg_samples[regval];
+ return 0;
+ case hwmon_chip_update_interval:
+ /* Return in msec */
+ *val = ina3221_reg_to_interval_us(ina->reg_config);
+ *val = DIV_ROUND_CLOSEST(*val, 1000);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val)
+{
+ const bool is_shunt = channel > INA3221_CHANNEL3;
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ u8 reg = ina3221_in_reg[channel];
+ int regval, ret;
+
+ /*
+ * Translate shunt channel index to sensor channel index except
+ * the 7th channel (6 since being 0-aligned) is for summation.
+ */
+ if (channel != 6)
+ channel %= INA3221_NUM_CHANNELS;
+
+ switch (attr) {
+ case hwmon_in_input:
+ if (!ina3221_is_enabled(ina, channel))
+ return -ENODATA;
+
+ /* Write CONFIG register to trigger a single-shot measurement */
+ if (ina->single_shot)
+ regmap_write(ina->regmap, INA3221_CONFIG,
+ ina->reg_config);
+
+ ret = ina3221_wait_for_data(ina);
+ if (ret)
+ return ret;
+
+ ret = ina3221_read_value(ina, reg, ®val);
+ if (ret)
+ return ret;
+
+ /*
+ * Scale of shunt voltage (uV): LSB is 40uV
+ * Scale of bus voltage (mV): LSB is 8mV
+ */
+ *val = regval * (is_shunt ? 40 : 8);
+ return 0;
+ case hwmon_in_enable:
+ *val = ina3221_is_enabled(ina, channel);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const u8 ina3221_curr_reg[][INA3221_NUM_CHANNELS + 1] = {
+ [hwmon_curr_input] = { INA3221_SHUNT1, INA3221_SHUNT2,
+ INA3221_SHUNT3, INA3221_SHUNT_SUM },
+ [hwmon_curr_max] = { INA3221_WARN1, INA3221_WARN2, INA3221_WARN3, 0 },
+ [hwmon_curr_crit] = { INA3221_CRIT1, INA3221_CRIT2,
+ INA3221_CRIT3, INA3221_CRIT_SUM },
+ [hwmon_curr_max_alarm] = { F_WF1, F_WF2, F_WF3, 0 },
+ [hwmon_curr_crit_alarm] = { F_CF1, F_CF2, F_CF3, F_SF },
+};
+
+static int ina3221_read_curr(struct device *dev, u32 attr,
+ int channel, long *val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ struct ina3221_input *input = ina->inputs;
+ u8 reg = ina3221_curr_reg[attr][channel];
+ int resistance_uo, voltage_nv;
+ int regval, ret;
+
+ if (channel > INA3221_CHANNEL3)
+ resistance_uo = ina->summation_shunt_resistor;
+ else
+ resistance_uo = input[channel].shunt_resistor;
+
+ switch (attr) {
+ case hwmon_curr_input:
+ if (!ina3221_is_enabled(ina, channel))
+ return -ENODATA;
+
+ /* Write CONFIG register to trigger a single-shot measurement */
+ if (ina->single_shot)
+ regmap_write(ina->regmap, INA3221_CONFIG,
+ ina->reg_config);
+
+ ret = ina3221_wait_for_data(ina);
+ if (ret)
+ return ret;
+
+ fallthrough;
+ case hwmon_curr_crit:
+ case hwmon_curr_max:
+ if (!resistance_uo)
+ return -ENODATA;
+
+ ret = ina3221_read_value(ina, reg, ®val);
+ if (ret)
+ return ret;
+
+ /* Scale of shunt voltage: LSB is 40uV (40000nV) */
+ voltage_nv = regval * 40000;
+ /* Return current in mA */
+ *val = DIV_ROUND_CLOSEST(voltage_nv, resistance_uo);
+ return 0;
+ case hwmon_curr_crit_alarm:
+ case hwmon_curr_max_alarm:
+ /* No actual register read if channel is disabled */
+ if (!ina3221_is_enabled(ina, channel)) {
+ /* Return 0 for alert flags */
+ *val = 0;
+ return 0;
+ }
+ ret = regmap_field_read(ina->fields[reg], ®val);
+ if (ret)
+ return ret;
+ *val = regval;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int ina3221_write_chip(struct device *dev, u32 attr, long val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ int ret, idx;
+ u32 tmp;
+
+ switch (attr) {
+ case hwmon_chip_samples:
+ idx = find_closest(val, ina3221_avg_samples,
+ ARRAY_SIZE(ina3221_avg_samples));
+
+ tmp = (ina->reg_config & ~INA3221_CONFIG_AVG_MASK) |
+ (idx << INA3221_CONFIG_AVG_SHIFT);
+ ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp);
+ if (ret)
+ return ret;
+
+ /* Update reg_config accordingly */
+ ina->reg_config = tmp;
+ return 0;
+ case hwmon_chip_update_interval:
+ tmp = ina3221_interval_ms_to_conv_time(ina->reg_config, val);
+ idx = find_closest(tmp, ina3221_conv_time,
+ ARRAY_SIZE(ina3221_conv_time));
+
+ /* Update Bus and Shunt voltage conversion times */
+ tmp = INA3221_CONFIG_VBUS_CT_MASK | INA3221_CONFIG_VSH_CT_MASK;
+ tmp = (ina->reg_config & ~tmp) |
+ (idx << INA3221_CONFIG_VBUS_CT_SHIFT) |
+ (idx << INA3221_CONFIG_VSH_CT_SHIFT);
+ ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp);
+ if (ret)
+ return ret;
+
+ /* Update reg_config accordingly */
+ ina->reg_config = tmp;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int ina3221_write_curr(struct device *dev, u32 attr,
+ int channel, long val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ struct ina3221_input *input = ina->inputs;
+ u8 reg = ina3221_curr_reg[attr][channel];
+ int resistance_uo, current_ma, voltage_uv;
+ int regval;
+
+ if (channel > INA3221_CHANNEL3)
+ resistance_uo = ina->summation_shunt_resistor;
+ else
+ resistance_uo = input[channel].shunt_resistor;
+
+ if (!resistance_uo)
+ return -EOPNOTSUPP;
+
+ /* clamp current */
+ current_ma = clamp_val(val,
+ INT_MIN / resistance_uo,
+ INT_MAX / resistance_uo);
+
+ voltage_uv = DIV_ROUND_CLOSEST(current_ma * resistance_uo, 1000);
+
+ /* clamp voltage */
+ voltage_uv = clamp_val(voltage_uv, -163800, 163800);
+
+ /*
+ * Formula to convert voltage_uv to register value:
+ * regval = (voltage_uv / scale) << shift
+ * Note:
+ * The scale is 40uV for all shunt voltage registers
+ * Shunt Voltage Sum register left-shifts 1 bit
+ * All other Shunt Voltage registers shift 3 bits
+ * Results:
+ * SHUNT_SUM: (1 / 40uV) << 1 = 1 / 20uV
+ * SHUNT[1-3]: (1 / 40uV) << 3 = 1 / 5uV
+ */
+ if (reg == INA3221_SHUNT_SUM)
+ regval = DIV_ROUND_CLOSEST(voltage_uv, 20) & 0xfffe;
+ else
+ regval = DIV_ROUND_CLOSEST(voltage_uv, 5) & 0xfff8;
+
+ return regmap_write(ina->regmap, reg, regval);
+}
+
+static int ina3221_write_enable(struct device *dev, int channel, bool enable)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ u16 config, mask = INA3221_CONFIG_CHx_EN(channel);
+ u16 config_old = ina->reg_config & mask;
+ u32 tmp;
+ int ret;
+
+ config = enable ? mask : 0;
+
+ /* Bypass if enable status is not being changed */
+ if (config_old == config)
+ return 0;
+
+ /* For enabling routine, increase refcount and resume() at first */
+ if (enable) {
+ ret = pm_runtime_resume_and_get(ina->pm_dev);
+ if (ret < 0) {
+ dev_err(dev, "Failed to get PM runtime\n");
+ return ret;
+ }
+ }
+
+ /* Enable or disable the channel */
+ tmp = (ina->reg_config & ~mask) | (config & mask);
+ ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp);
+ if (ret)
+ goto fail;
+
+ /* Cache the latest config register value */
+ ina->reg_config = tmp;
+
+ /* For disabling routine, decrease refcount or suspend() at last */
+ if (!enable)
+ pm_runtime_put_sync(ina->pm_dev);
+
+ return 0;
+
+fail:
+ if (enable) {
+ dev_err(dev, "Failed to enable channel %d: error %d\n",
+ channel, ret);
+ pm_runtime_put_sync(ina->pm_dev);
+ }
+
+ return ret;
+}
+
+static int ina3221_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ int ret;
+
+ mutex_lock(&ina->lock);
+
+ switch (type) {
+ case hwmon_chip:
+ ret = ina3221_read_chip(dev, attr, val);
+ break;
+ case hwmon_in:
+ /* 0-align channel ID */
+ ret = ina3221_read_in(dev, attr, channel - 1, val);
+ break;
+ case hwmon_curr:
+ ret = ina3221_read_curr(dev, attr, channel, val);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ mutex_unlock(&ina->lock);
+
+ return ret;
+}
+
+static int ina3221_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ int ret;
+
+ mutex_lock(&ina->lock);
+
+ switch (type) {
+ case hwmon_chip:
+ ret = ina3221_write_chip(dev, attr, val);
+ break;
+ case hwmon_in:
+ /* 0-align channel ID */
+ ret = ina3221_write_enable(dev, channel - 1, val);
+ break;
+ case hwmon_curr:
+ ret = ina3221_write_curr(dev, attr, channel, val);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ mutex_unlock(&ina->lock);
+
+ return ret;
+}
+
+static int ina3221_read_string(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ int index = channel - 1;
+
+ if (channel == 7)
+ *str = "sum of shunt voltages";
+ else
+ *str = ina->inputs[index].label;
+
+ return 0;
+}
+
+static umode_t ina3221_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct ina3221_data *ina = drvdata;
+ const struct ina3221_input *input = NULL;
+
+ switch (type) {
+ case hwmon_chip:
+ switch (attr) {
+ case hwmon_chip_samples:
+ case hwmon_chip_update_interval:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_in:
+ /* Ignore in0_ */
+ if (channel == 0)
+ return 0;
+
+ switch (attr) {
+ case hwmon_in_label:
+ if (channel - 1 <= INA3221_CHANNEL3)
+ input = &ina->inputs[channel - 1];
+ else if (channel == 7)
+ return 0444;
+ /* Hide label node if label is not provided */
+ return (input && input->label) ? 0444 : 0;
+ case hwmon_in_input:
+ return 0444;
+ case hwmon_in_enable:
+ return 0644;
+ default:
+ return 0;
+ }
+ case hwmon_curr:
+ switch (attr) {
+ case hwmon_curr_input:
+ case hwmon_curr_crit_alarm:
+ case hwmon_curr_max_alarm:
+ return 0444;
+ case hwmon_curr_crit:
+ case hwmon_curr_max:
+ return 0644;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+#define INA3221_HWMON_CURR_CONFIG (HWMON_C_INPUT | \
+ HWMON_C_CRIT | HWMON_C_CRIT_ALARM | \
+ HWMON_C_MAX | HWMON_C_MAX_ALARM)
+
+static const struct hwmon_channel_info *ina3221_info[] = {
+ HWMON_CHANNEL_INFO(chip,
+ HWMON_C_SAMPLES,
+ HWMON_C_UPDATE_INTERVAL),
+ HWMON_CHANNEL_INFO(in,
+ /* 0: dummy, skipped in is_visible */
+ HWMON_I_INPUT,
+ /* 1-3: input voltage Channels */
+ HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
+ /* 4-6: shunt voltage Channels */
+ HWMON_I_INPUT,
+ HWMON_I_INPUT,
+ HWMON_I_INPUT,
+ /* 7: summation of shunt voltage channels */
+ HWMON_I_INPUT | HWMON_I_LABEL),
+ HWMON_CHANNEL_INFO(curr,
+ /* 1-3: current channels*/
+ INA3221_HWMON_CURR_CONFIG,
+ INA3221_HWMON_CURR_CONFIG,
+ INA3221_HWMON_CURR_CONFIG,
+ /* 4: summation of current channels */
+ HWMON_C_INPUT | HWMON_C_CRIT | HWMON_C_CRIT_ALARM),
+ NULL
+};
+
+static const struct hwmon_ops ina3221_hwmon_ops = {
+ .is_visible = ina3221_is_visible,
+ .read_string = ina3221_read_string,
+ .read = ina3221_read,
+ .write = ina3221_write,
+};
+
+static const struct hwmon_chip_info ina3221_chip_info = {
+ .ops = &ina3221_hwmon_ops,
+ .info = ina3221_info,
+};
+
+/* Extra attribute groups */
+static ssize_t ina3221_shunt_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ unsigned int channel = sd_attr->index;
+ struct ina3221_input *input = &ina->inputs[channel];
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", input->shunt_resistor);
+}
+
+static ssize_t ina3221_shunt_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(attr);
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ unsigned int channel = sd_attr->index;
+ struct ina3221_input *input = &ina->inputs[channel];
+ int val;
+ int ret;
+
+ ret = kstrtoint(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ val = clamp_val(val, 1, INT_MAX);
+
+ input->shunt_resistor = val;
+
+ /* Update summation_shunt_resistor for summation channel */
+ ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina);
+
+ return count;
+}
+
+/* shunt resistance */
+static SENSOR_DEVICE_ATTR_RW(shunt1_resistor, ina3221_shunt, INA3221_CHANNEL1);
+static SENSOR_DEVICE_ATTR_RW(shunt2_resistor, ina3221_shunt, INA3221_CHANNEL2);
+static SENSOR_DEVICE_ATTR_RW(shunt3_resistor, ina3221_shunt, INA3221_CHANNEL3);
+
+static struct attribute *ina3221_attrs[] = {
+ &sensor_dev_attr_shunt1_resistor.dev_attr.attr,
+ &sensor_dev_attr_shunt2_resistor.dev_attr.attr,
+ &sensor_dev_attr_shunt3_resistor.dev_attr.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(ina3221);
+
+static const struct regmap_range ina3221_yes_ranges[] = {
+ regmap_reg_range(INA3221_CONFIG, INA3221_BUS3),
+ regmap_reg_range(INA3221_SHUNT_SUM, INA3221_SHUNT_SUM),
+ regmap_reg_range(INA3221_MASK_ENABLE, INA3221_MASK_ENABLE),
+};
+
+static const struct regmap_access_table ina3221_volatile_table = {
+ .yes_ranges = ina3221_yes_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ina3221_yes_ranges),
+};
+
+static const struct regmap_config ina3221_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_table = &ina3221_volatile_table,
+};
+
+static int ina3221_probe_child_from_dt(struct device *dev,
+ struct device_node *child,
+ struct ina3221_data *ina)
+{
+ struct ina3221_input *input;
+ u32 val;
+ int ret;
+
+ ret = of_property_read_u32(child, "reg", &val);
+ if (ret) {
+ dev_err(dev, "missing reg property of %pOFn\n", child);
+ return ret;
+ } else if (val > INA3221_CHANNEL3) {
+ dev_err(dev, "invalid reg %d of %pOFn\n", val, child);
+ return ret;
+ }
+
+ input = &ina->inputs[val];
+
+ /* Log the disconnected channel input */
+ if (!of_device_is_available(child)) {
+ input->disconnected = true;
+ return 0;
+ }
+
+ /* Save the connected input label if available */
+ of_property_read_string(child, "label", &input->label);
+
+ /* Overwrite default shunt resistor value optionally */
+ if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val)) {
+ if (val < 1 || val > INT_MAX) {
+ dev_err(dev, "invalid shunt resistor value %u of %pOFn\n",
+ val, child);
+ return -EINVAL;
+ }
+ input->shunt_resistor = val;
+ }
+
+ return 0;
+}
+
+static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina)
+{
+ const struct device_node *np = dev->of_node;
+ struct device_node *child;
+ int ret;
+
+ /* Compatible with non-DT platforms */
+ if (!np)
+ return 0;
+
+ ina->single_shot = of_property_read_bool(np, "ti,single-shot");
+
+ for_each_child_of_node(np, child) {
+ ret = ina3221_probe_child_from_dt(dev, child, ina);
+ if (ret) {
+ of_node_put(child);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int ina3221_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct ina3221_data *ina;
+ struct device *hwmon_dev;
+ int i, ret;
+
+ ina = devm_kzalloc(dev, sizeof(*ina), GFP_KERNEL);
+ if (!ina)
+ return -ENOMEM;
+
+ ina->regmap = devm_regmap_init_i2c(client, &ina3221_regmap_config);
+ if (IS_ERR(ina->regmap)) {
+ dev_err(dev, "Unable to allocate register map\n");
+ return PTR_ERR(ina->regmap);
+ }
+
+ for (i = 0; i < F_MAX_FIELDS; i++) {
+ ina->fields[i] = devm_regmap_field_alloc(dev,
+ ina->regmap,
+ ina3221_reg_fields[i]);
+ if (IS_ERR(ina->fields[i])) {
+ dev_err(dev, "Unable to allocate regmap fields\n");
+ return PTR_ERR(ina->fields[i]);
+ }
+ }
+
+ for (i = 0; i < INA3221_NUM_CHANNELS; i++)
+ ina->inputs[i].shunt_resistor = INA3221_RSHUNT_DEFAULT;
+
+ ret = ina3221_probe_from_dt(dev, ina);
+ if (ret) {
+ dev_err(dev, "Unable to probe from device tree\n");
+ return ret;
+ }
+
+ /* The driver will be reset, so use reset value */
+ ina->reg_config = INA3221_CONFIG_DEFAULT;
+
+ /* Clear continuous bit to use single-shot mode */
+ if (ina->single_shot)
+ ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS;
+
+ /* Disable channels if their inputs are disconnected */
+ for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
+ if (ina->inputs[i].disconnected)
+ ina->reg_config &= ~INA3221_CONFIG_CHx_EN(i);
+ }
+
+ /* Initialize summation_shunt_resistor for summation channel control */
+ ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina);
+
+ ina->pm_dev = dev;
+ mutex_init(&ina->lock);
+ dev_set_drvdata(dev, ina);
+
+ /* Enable PM runtime -- status is suspended by default */
+ pm_runtime_enable(ina->pm_dev);
+
+ /* Initialize (resume) the device */
+ for (i = 0; i < INA3221_NUM_CHANNELS; i++) {
+ if (ina->inputs[i].disconnected)
+ continue;
+ /* Match the refcount with number of enabled channels */
+ ret = pm_runtime_get_sync(ina->pm_dev);
+ if (ret < 0)
+ goto fail;
+ }
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, ina,
+ &ina3221_chip_info,
+ ina3221_groups);
+ if (IS_ERR(hwmon_dev)) {
+ dev_err(dev, "Unable to register hwmon device\n");
+ ret = PTR_ERR(hwmon_dev);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ pm_runtime_disable(ina->pm_dev);
+ pm_runtime_set_suspended(ina->pm_dev);
+ /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */
+ for (i = 0; i < INA3221_NUM_CHANNELS; i++)
+ pm_runtime_put_noidle(ina->pm_dev);
+ mutex_destroy(&ina->lock);
+
+ return ret;
+}
+
+static void ina3221_remove(struct i2c_client *client)
+{
+ struct ina3221_data *ina = dev_get_drvdata(&client->dev);
+ int i;
+
+ pm_runtime_disable(ina->pm_dev);
+ pm_runtime_set_suspended(ina->pm_dev);
+
+ /* pm_runtime_put_noidle() will decrease the PM refcount until 0 */
+ for (i = 0; i < INA3221_NUM_CHANNELS; i++)
+ pm_runtime_put_noidle(ina->pm_dev);
+
+ mutex_destroy(&ina->lock);
+
+ return;
+}
+
+static int __maybe_unused ina3221_suspend(struct device *dev)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ int ret;
+
+ /* Save config register value and enable cache-only */
+ ret = regmap_read(ina->regmap, INA3221_CONFIG, &ina->reg_config);
+ if (ret)
+ return ret;
+
+ /* Set to power-down mode for power saving */
+ ret = regmap_update_bits(ina->regmap, INA3221_CONFIG,
+ INA3221_CONFIG_MODE_MASK,
+ INA3221_CONFIG_MODE_POWERDOWN);
+ if (ret)
+ return ret;
+
+ regcache_cache_only(ina->regmap, true);
+ regcache_mark_dirty(ina->regmap);
+
+ return 0;
+}
+
+static int __maybe_unused ina3221_resume(struct device *dev)
+{
+ struct ina3221_data *ina = dev_get_drvdata(dev);
+ int ret;
+
+ regcache_cache_only(ina->regmap, false);
+
+ /* Software reset the chip */
+ ret = regmap_field_write(ina->fields[F_RST], true);
+ if (ret) {
+ dev_err(dev, "Unable to reset device\n");
+ return ret;
+ }
+
+ /* Restore cached register values to hardware */
+ ret = regcache_sync(ina->regmap);
+ if (ret)
+ return ret;
+
+ /* Restore config register value to hardware */
+ ret = regmap_write(ina->regmap, INA3221_CONFIG, ina->reg_config);
+ if (ret)
+ return ret;
+
+ /* Initialize summation channel control */
+ if (ina->summation_shunt_resistor) {
+ /*
+ * Take all three channels into summation by default
+ * Shunt measurements of disconnected channels should
+ * be 0, so it does not matter for summation.
+ */
+ ret = regmap_update_bits(ina->regmap, INA3221_MASK_ENABLE,
+ INA3221_MASK_ENABLE_SCC_MASK,
+ INA3221_MASK_ENABLE_SCC_MASK);
+ if (ret) {
+ dev_err(dev, "Unable to control summation channel\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops ina3221_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(ina3221_suspend, ina3221_resume, NULL)
+};
+
+static const struct of_device_id ina3221_of_match_table[] = {
+ { .compatible = "ti,wb_ina3221", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ina3221_of_match_table);
+
+static const struct i2c_device_id ina3221_ids[] = {
+ { "wb_ina3221", 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, ina3221_ids);
+
+static struct i2c_driver ina3221_i2c_driver = {
+ .probe_new = ina3221_probe,
+ .remove = ina3221_remove,
+ .driver = {
+ .name = INA3221_DRIVER_NAME,
+ .of_match_table = ina3221_of_match_table,
+ .pm = &ina3221_pm,
+ },
+ .id_table = ina3221_ids,
+};
+module_i2c_driver(ina3221_i2c_driver);
+
+MODULE_AUTHOR("support");
+MODULE_DESCRIPTION("Texas Instruments INA3221 HWMon Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_isl68137.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_isl68137.c
new file mode 100644
index 000000000000..648020435311
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/linux-5.10/wb_isl68137.c
@@ -0,0 +1,577 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Hardware monitoring driver for Renesas Digital Multiphase Voltage Regulators
+ *
+ * Copyright (c) 2017 Google Inc
+ * Copyright (c) 2020 Renesas Electronics America
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include