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..cadf2fb312eb
--- /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"
+ },
+ "Ethernet5": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet9": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet13": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet17": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet21": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet25": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet29": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet33": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet37": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet41": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet45": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet49": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet53": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet57": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet61": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet65": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet69": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet73": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet77": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet81": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet85": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet89": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet93": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet97": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet105": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet113": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet121": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet129": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet137": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet145": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet153": {
+ "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..1a166a9a8367
--- /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
+Ethernet5 29,30,31,32 twoHundredGigE0/2 1 200000
+Ethernet9 41,42,43,44 twoHundredGigE0/3 2 200000
+Ethernet13 45,46,47,48 twoHundredGigE0/4 3 200000
+Ethernet17 49,50,51,52 twoHundredGigE0/5 4 200000
+Ethernet21 53,54,55,56 twoHundredGigE0/6 5 200000
+Ethernet25 57,58,59,60 twoHundredGigE0/7 6 200000
+Ethernet29 61,62,63,64 twoHundredGigE0/8 7 200000
+Ethernet33 9,10,11,12 twoHundredGigE0/9 8 200000
+Ethernet37 13,14,15,16 twoHundredGigE0/10 9 200000
+Ethernet41 17,18,19,20 twoHundredGigE0/11 10 200000
+Ethernet45 21,22,23,24 twoHundredGigE0/12 11 200000
+Ethernet49 81,82,83,84 twoHundredGigE0/13 12 200000
+Ethernet53 85,86,87,88 twoHundredGigE0/14 13 200000
+Ethernet57 89,90,91,92 twoHundredGigE0/15 14 200000
+Ethernet61 93,94,95,96 twoHundredGigE0/16 15 200000
+Ethernet65 97,98,99,100 twoHundredGigE0/17 16 200000
+Ethernet69 101,102,103,104 twoHundredGigE0/18 17 200000
+Ethernet73 137,138,139,140 twoHundredGigE0/19 18 200000
+Ethernet77 141,142,143,144 twoHundredGigE0/20 19 200000
+Ethernet81 145,146,147,148 twoHundredGigE0/21 20 200000
+Ethernet85 149,150,151,152 twoHundredGigE0/22 21 200000
+Ethernet89 153,154,155,156 twoHundredGigE0/23 22 200000
+Ethernet93 157,158,159,160 twoHundredGigE0/24 23 200000
+Ethernet97 1,2,3,4,5,6,7,8 fourHundredGigE0/1 24 400000
+Ethernet105 33,34,35,36,37,38,39,40 fourHundredGigE0/2 25 400000
+Ethernet113 65,66,67,68,69,70,71,72 fourHundredGigE0/3 26 400000
+Ethernet121 73,74,75,76,77,78,79,80 fourHundredGigE0/4 27 400000
+Ethernet129 105,106,107,108,109,110,111,112 fourHundredGigE0/5 28 400000
+Ethernet137 113,114,115,116,117,118,119,120 fourHundredGigE0/6 29 400000
+Ethernet145 121,122,123,124,125,126,127,128 fourHundredGigE0/7 30 400000
+Ethernet153 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..8a7c7a7e9fbc
--- /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,4114 @@
+---
+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
+ sai_pfc_defaults_disable: 1
+ sai_postinit_cmd_file: /usr/share/sonic/platform/postinit_cmd_file.soc
+...
+
+---
+bcm_device:
+ 0:
+ port:
+ 11:
+ dport_map_port: 1
+ 12:
+ dport_map_port: 2
+ 13:
+ dport_map_port: 3
+ 14:
+ dport_map_port: 4
+ 20:
+ dport_map_port: 5
+ 21:
+ dport_map_port: 6
+ 22:
+ dport_map_port: 7
+ 23:
+ dport_map_port: 8
+ 24:
+ dport_map_port: 9
+ 25:
+ dport_map_port: 10
+ 26:
+ dport_map_port: 11
+ 27:
+ dport_map_port: 12
+ 28:
+ dport_map_port: 13
+ 29:
+ dport_map_port: 14
+ 30:
+ dport_map_port: 15
+ 31:
+ dport_map_port: 16
+ 3:
+ dport_map_port: 17
+ 4:
+ dport_map_port: 18
+ 5:
+ dport_map_port: 19
+ 6:
+ dport_map_port: 20
+ 7:
+ dport_map_port: 21
+ 8:
+ dport_map_port: 22
+ 9:
+ dport_map_port: 23
+ 10:
+ dport_map_port: 24
+ 40:
+ dport_map_port: 25
+ 41:
+ dport_map_port: 26
+ 42:
+ dport_map_port: 27
+ 43:
+ dport_map_port: 28
+ 44:
+ dport_map_port: 29
+ 45:
+ dport_map_port: 30
+ 46:
+ dport_map_port: 31
+ 47:
+ dport_map_port: 32
+ 48:
+ dport_map_port: 33
+ 49:
+ dport_map_port: 34
+ 50:
+ dport_map_port: 35
+ 51:
+ dport_map_port: 36
+ 64:
+ dport_map_port: 37
+ 65:
+ dport_map_port: 38
+ 66:
+ dport_map_port: 39
+ 67:
+ dport_map_port: 40
+ 68:
+ dport_map_port: 41
+ 69:
+ dport_map_port: 42
+ 70:
+ dport_map_port: 43
+ 71:
+ dport_map_port: 44
+ 72:
+ dport_map_port: 45
+ 73:
+ dport_map_port: 46
+ 74:
+ dport_map_port: 47
+ 75:
+ dport_map_port: 48
+ 1:
+ dport_map_port: 49
+ 2:
+ dport_map_port: 50
+ 15:
+ dport_map_port: 51
+ 16:
+ dport_map_port: 52
+ 32:
+ dport_map_port: 53
+ 33:
+ dport_map_port: 54
+ 34:
+ dport_map_port: 55
+ 35:
+ dport_map_port: 56
+ 52:
+ dport_map_port: 57
+ 53:
+ dport_map_port: 58
+ 54:
+ dport_map_port: 59
+ 55:
+ dport_map_port: 60
+ 60:
+ dport_map_port: 61
+ 61:
+ dport_map_port: 62
+ 62:
+ dport_map_port: 63
+ 63:
+ dport_map_port: 64
+...
+
+---
+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..779f4b79d1b9
--- /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,4125 @@
+---
+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
+ sai_nbr_bcast_ifp_optimized: 2
+ uft_mode: 1
+ l3_enable: 1
+ l2_hitbit_enable: 0
+ pktio_mode: 1
+ sai_optimized_mmu: 1
+ sai_pfc_defaults_disable: 1
+ warmboot_knet_shutdown_mode: 1
+ sai_postinit_cmd_file: /usr/share/sonic/platform/postinit_cmd_file.soc
+...
+
+---
+device:
+ 0:
+ FP_CONFIG:
+ #FP_ING_OPERMODE: PIPE_UNIQUE
+ FP_ING_OPERMODE: GLOBAL_PIPE_AWARE
+...
+
+---
+bcm_device:
+ 0:
+ port:
+ 11:
+ dport_map_port: 1
+ 12:
+ dport_map_port: 2
+ 13:
+ dport_map_port: 3
+ 14:
+ dport_map_port: 4
+ 20:
+ dport_map_port: 5
+ 21:
+ dport_map_port: 6
+ 22:
+ dport_map_port: 7
+ 23:
+ dport_map_port: 8
+ 24:
+ dport_map_port: 9
+ 25:
+ dport_map_port: 10
+ 26:
+ dport_map_port: 11
+ 27:
+ dport_map_port: 12
+ 28:
+ dport_map_port: 13
+ 29:
+ dport_map_port: 14
+ 30:
+ dport_map_port: 15
+ 31:
+ dport_map_port: 16
+ 3:
+ dport_map_port: 17
+ 4:
+ dport_map_port: 18
+ 5:
+ dport_map_port: 19
+ 6:
+ dport_map_port: 20
+ 7:
+ dport_map_port: 21
+ 8:
+ dport_map_port: 22
+ 9:
+ dport_map_port: 23
+ 10:
+ dport_map_port: 24
+ 40:
+ dport_map_port: 25
+ 41:
+ dport_map_port: 26
+ 42:
+ dport_map_port: 27
+ 43:
+ dport_map_port: 28
+ 44:
+ dport_map_port: 29
+ 45:
+ dport_map_port: 30
+ 46:
+ dport_map_port: 31
+ 47:
+ dport_map_port: 32
+ 48:
+ dport_map_port: 33
+ 49:
+ dport_map_port: 34
+ 50:
+ dport_map_port: 35
+ 51:
+ dport_map_port: 36
+ 64:
+ dport_map_port: 37
+ 65:
+ dport_map_port: 38
+ 66:
+ dport_map_port: 39
+ 67:
+ dport_map_port: 40
+ 68:
+ dport_map_port: 41
+ 69:
+ dport_map_port: 42
+ 70:
+ dport_map_port: 43
+ 71:
+ dport_map_port: 44
+ 72:
+ dport_map_port: 45
+ 73:
+ dport_map_port: 46
+ 74:
+ dport_map_port: 47
+ 75:
+ dport_map_port: 48
+ 1:
+ dport_map_port: 49
+ 2:
+ dport_map_port: 50
+ 15:
+ dport_map_port: 51
+ 16:
+ dport_map_port: 52
+ 32:
+ dport_map_port: 53
+ 33:
+ dport_map_port: 54
+ 34:
+ dport_map_port: 55
+ 35:
+ dport_map_port: 56
+ 52:
+ dport_map_port: 57
+ 53:
+ dport_map_port: 58
+ 54:
+ dport_map_port: 59
+ 55:
+ dport_map_port: 60
+ 60:
+ dport_map_port: 61
+ 61:
+ dport_map_port: 62
+ 62:
+ dport_map_port: 63
+ 63:
+ dport_map_port: 64
+...
+
+---
+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..b3185be90620
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..cadf2fb312eb
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/hwsku.json
@@ -0,0 +1,100 @@
+{
+ "interfaces": {
+ "Ethernet1": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet5": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet9": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet13": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet17": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet21": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet25": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet29": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet33": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet37": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet41": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet45": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet49": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet53": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet57": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet61": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet65": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet69": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet73": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet77": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet81": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet85": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet89": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet93": {
+ "default_brkout_mode": "1x200G"
+ },
+ "Ethernet97": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet105": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet113": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet121": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet129": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet137": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet145": {
+ "default_brkout_mode": "1x400G"
+ },
+ "Ethernet153": {
+ "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..7a9fec8cc99c
--- /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"
\ No newline at end of file
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..1d7f598d2fe8
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/media_settings.json
@@ -0,0 +1,1476 @@
+{
+ "PORT_MEDIA_SETTINGS": {
+ "0": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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": {
+ "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"
+ }
+ }
+ }
+ }
+}
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..5fc287892e50
--- /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
+from lxml import etree 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.update(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 100644
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..d22eee94c31b
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/platform.json
@@ -0,0 +1,1010 @@
+{
+ "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"
+ ],
+ "2x100G": [
+ "Eth1/1",
+ "Eth1/2"
+ ]
+ }
+ },
+ "Ethernet5": {
+ "index": "1,1,1,1",
+ "lanes": "29,30,31,32",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth2"
+ ],
+ "2x100G": [
+ "Eth2/1",
+ "Eth2/2"
+ ]
+ }
+ },
+ "Ethernet9": {
+ "index": "2,2,2,2",
+ "lanes": "41,42,43,44",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth3"
+ ],
+ "2x100G": [
+ "Eth3/1",
+ "Eth3/2"
+ ]
+ }
+ },
+ "Ethernet13": {
+ "index": "3,3,3,3",
+ "lanes": "45,46,47,48",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth4"
+ ],
+ "2x100G": [
+ "Eth4/1",
+ "Eth4/2"
+ ]
+ }
+ },
+ "Ethernet17": {
+ "index": "4,4,4,4",
+ "lanes": "49,50,51,52",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth5"
+ ],
+ "2x100G": [
+ "Eth5/1",
+ "Eth5/2"
+ ]
+ }
+ },
+ "Ethernet21": {
+ "index": "5,5,5,5",
+ "lanes": "53,54,55,56",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth6"
+ ],
+ "2x100G": [
+ "Eth6/1",
+ "Eth6/2"
+ ]
+ }
+ },
+ "Ethernet25": {
+ "index": "6,6,6,6",
+ "lanes": "57,58,59,60",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth7"
+ ],
+ "2x100G": [
+ "Eth7/1",
+ "Eth7/2"
+ ]
+ }
+ },
+ "Ethernet29": {
+ "index": "7,7,7,7",
+ "lanes": "61,62,63,64",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth8"
+ ],
+ "2x100G": [
+ "Eth8/1",
+ "Eth8/2"
+ ]
+ }
+ },
+ "Ethernet33": {
+ "index": "8,8,8,8",
+ "lanes": "9,10,11,12",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth9"
+ ],
+ "2x100G": [
+ "Eth9/1",
+ "Eth9/2"
+ ]
+ }
+ },
+ "Ethernet37": {
+ "index": "9,9,9,9",
+ "lanes": "13,14,15,16",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth10"
+ ],
+ "2x100G": [
+ "Eth10/1",
+ "Eth10/2"
+ ]
+ }
+ },
+ "Ethernet41": {
+ "index": "10,10,10,10",
+ "lanes": "17,18,19,20",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth11"
+ ],
+ "2x100G": [
+ "Eth11/1",
+ "Eth11/2"
+ ]
+ }
+ },
+ "Ethernet45": {
+ "index": "11,11,11,11",
+ "lanes": "21,22,23,24",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth12"
+ ],
+ "2x100G": [
+ "Eth12/1",
+ "Eth12/2"
+ ]
+ }
+ },
+ "Ethernet49": {
+ "index": "12,12,12,12",
+ "lanes": "81,82,83,84",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth13"
+ ],
+ "2x100G": [
+ "Eth13/1",
+ "Eth13/2"
+ ]
+ }
+ },
+ "Ethernet53": {
+ "index": "13,13,13,13",
+ "lanes": "85,86,87,88",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth14"
+ ],
+ "2x100G": [
+ "Eth14/1",
+ "Eth14/2"
+ ]
+ }
+ },
+ "Ethernet57": {
+ "index": "14,14,14,14",
+ "lanes": "89,90,91,92",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth15"
+ ],
+ "2x100G": [
+ "Eth15/1",
+ "Eth15/2"
+ ]
+ }
+ },
+ "Ethernet61": {
+ "index": "15,15,15,15",
+ "lanes": "93,94,95,96",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth16"
+ ],
+ "2x100G": [
+ "Eth16/1",
+ "Eth16/2"
+ ]
+ }
+ },
+ "Ethernet65": {
+ "index": "16,16,16,16",
+ "lanes": "97,98,99,100",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth17"
+ ],
+ "2x100G": [
+ "Eth17/1",
+ "Eth17/2"
+ ]
+ }
+ },
+ "Ethernet69": {
+ "index": "17,17,17,17",
+ "lanes": "101,102,103,104",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth18"
+ ],
+ "2x100G": [
+ "Eth18/1",
+ "Eth18/2"
+ ]
+ }
+ },
+ "Ethernet73": {
+ "index": "18,18,18,18",
+ "lanes": "137,138,139,140",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth19"
+ ],
+ "2x100G": [
+ "Eth19/1",
+ "Eth19/2"
+ ]
+ }
+ },
+ "Ethernet77": {
+ "index": "19,19,19,19",
+ "lanes": "141,142,143,144",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth20"
+ ],
+ "2x100G": [
+ "Eth20/1",
+ "Eth20/2"
+ ]
+ }
+ },
+ "Ethernet81": {
+ "index": "20,20,20,20",
+ "lanes": "145,146,147,148",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth21"
+ ],
+ "2x100G": [
+ "Eth21/1",
+ "Eth21/2"
+ ]
+ }
+ },
+ "Ethernet85": {
+ "index": "21,21,21,21",
+ "lanes": "149,150,151,152",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth22"
+ ],
+ "2x100G": [
+ "Eth22/1",
+ "Eth22/2"
+ ]
+ }
+ },
+ "Ethernet89": {
+ "index": "22,22,22,22",
+ "lanes": "153,154,155,156",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth23"
+ ],
+ "2x100G": [
+ "Eth23/1",
+ "Eth23/2"
+ ]
+ }
+ },
+ "Ethernet93": {
+ "index": "23,23,23,23",
+ "lanes": "157,158,159,160",
+ "breakout_modes": {
+ "1x200G": [
+ "Eth24"
+ ],
+ "2x100G": [
+ "Eth24/1",
+ "Eth24/2"
+ ]
+ }
+ },
+ "Ethernet97": {
+ "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"
+ ]
+ }
+ },
+ "Ethernet105": {
+ "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"
+ ]
+ }
+ },
+ "Ethernet113": {
+ "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"
+ ]
+ }
+ },
+ "Ethernet121": {
+ "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"
+ ]
+ }
+ },
+ "Ethernet129": {
+ "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"
+ ]
+ }
+ },
+ "Ethernet137": {
+ "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"
+ ]
+ }
+ },
+ "Ethernet145": {
+ "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"
+ ]
+ }
+ },
+ "Ethernet153": {
+ "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..e8cf2e1a7cbc
--- /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_storage.storage_base import StorageBase
+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(StorageBase):
+ """
+ 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/postinit_cmd_file.soc b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/postinit_cmd_file.soc
new file mode 100644
index 000000000000..6167c3d68f33
--- /dev/null
+++ b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/postinit_cmd_file.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/system_health_monitoring_config.json b/device/micas/x86_64-micas_m2-w6520-24dc8qc-r0/system_health_monitoring_config.json
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index 38c1a9521388..caac3b74f1b0 100755
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -98,7 +98,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(UFISPACE_S9301_32D_PLATFORM_MODULE) \
$(UFISPACE_S9301_32DB_PLATFORM_MODULE) \
$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE) \
- $(MICAS_M2_W6510_48GT4V_PLATFORM_MODULE)
+ $(MICAS_M2_W6510_48GT4V_PLATFORM_MODULE) \
+ $(MICAS_M2_W6520_24DC8QC_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_BUILD_INSTALLS = $(BRCM_OPENNSL_KERNEL) $(BRCM_DNX_OPENNSL_KERNEL)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
diff --git a/platform/broadcom/platform-modules-micas.mk b/platform/broadcom/platform-modules-micas.mk
index 5b7fd2cdcb07..fb2277921950 100644
--- a/platform/broadcom/platform-modules-micas.mk
+++ b/platform/broadcom/platform-modules-micas.mk
@@ -16,3 +16,11 @@ export MICAS_M2_W6510_48GT4V_PLATFORM_MODULE_VERSION
MICAS_M2_W6510_48GT4V_PLATFORM_MODULE = platform-modules-micas-m2-w6510-48gt4v_$(MICAS_M2_W6510_48GT4V_PLATFORM_MODULE_VERSION)_amd64.deb
$(MICAS_M2_W6510_48GT4V_PLATFORM_MODULE)_PLATFORM = x86_64-micas_m2-w6510-48gt4v-r0
$(eval $(call add_extra_package,$(MICAS_M2_W6510_48V8C_PLATFORM_MODULE),$(MICAS_M2_W6510_48GT4V_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/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
index 93ed6066efed..71d6cd510a88 100644
--- 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
@@ -1,3 +1,23 @@
+/*
+ * An dfd_debug driver for dfd debug function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
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
index c82b0baad4c3..dbf5f8462eb6 100644
--- 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
@@ -1,3 +1,22 @@
+/*
+ * An dfd_utest driver for dfd utest function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#include
#include
@@ -1865,10 +1884,6 @@ static int mdiodev_arg_parse(int argc, char* argv[], int *mdio_index, int *phyad
}
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);
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
index 1ae65148ea9c..71445a449abd 100644
--- 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
@@ -1,4 +1,23 @@
-/* monitor_utest.h */
+/*
+ * A header definition for dfd_utest driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __DFD_UTEST_H__
#define __DFD_UTEST_H__
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
index 2045608d5c3b..7141ef08be56 100644
--- 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
@@ -1,3 +1,23 @@
+/*
+ * An fw_upgrade driver for firmware upgrade function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
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
index a7a78d011011..0ee3a6f52ef0 100644
--- 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
@@ -1,3 +1,23 @@
+/*
+ * An fw_upgrade_debug driver for firmware upgrade debug function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
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
index bd806a94b154..aa012b8ab6d7 100644
--- 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
@@ -1,3 +1,23 @@
+/*
+ * A header definition for fw_upgrade driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _FW_UPGRADE_H_
#define _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
index 05911da62a7e..bc6a6ff33404 100644
--- 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
@@ -1,3 +1,23 @@
+/*
+ * A header definition for fw_upgrade_debug driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __FW_UPGRADE_DEBUG_H__
#define __FW_UPGRADE_DEBUG_H__
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
index 81fd596e7fee..34aa0f8866ac 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/hysteresis.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/hysteresis.py
@@ -1,4 +1,20 @@
#!/usr/bin/env python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import os
import syslog
import copy
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
index 3bb46b286998..3a284230271c 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/openloop.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/openloop.py
@@ -1,4 +1,20 @@
#!/usr/bin/env python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import os
import syslog
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
index 25c2069fea66..93a4ec545627 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/pid.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/algorithm/pid.py
@@ -1,4 +1,20 @@
#!/usr/bin/env python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import os
import syslog
import copy
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
index 940c722ce467..ea401f78fd00 100644
--- 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
@@ -1,5 +1,20 @@
#!/usr/bin/python
-# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import sys
import os
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
index 4be78e7fdc03..f7f2d7731ed7 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fantlv.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fantlv.py
@@ -1,5 +1,19 @@
#!/usr/bin/python3
-# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
class FantlvException(Exception):
def __init__(self, message='fantlverror', code=-100):
@@ -32,18 +46,34 @@ def dstatus(self):
def typename(self):
return self._typename
+ @typename.setter
+ def typename(self, value):
+ self._typename = value
+
@property
def typesn(self):
return self._typesn
+ @typesn.setter
+ def typesn(self, value):
+ self._typesn = value
+
@property
def typehwinfo(self):
return self._typehwinfo
+ @typehwinfo.setter
+ def typehwinfo(self, value):
+ self._typehwinfo = value
+
@property
def typedevtype(self):
return self._typedevtype
+ @typedevtype.setter
+ def typedevtype(self, value):
+ self._typedevtype = value
+
def __init__(self):
self._typename = ""
self._typesn = ""
@@ -61,15 +91,15 @@ def strtoarr(self, val):
def hex_to_str(self, s):
len_t = len(s)
- if len_t % 2 != 0:
+ if int(len_t % 2) != 0:
return 0
ret = ""
- for t in range(0, len_t / 2):
+ for t in range(0, int(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
+ def generate_fan_value(self, size=256):
+ bin_buffer = [chr(0x00)] * size
bin_buffer[0] = chr(self.VERSION)
bin_buffer[1] = chr(self.FLAG)
bin_buffer[2] = chr(self.HW_VER)
@@ -80,6 +110,10 @@ def generate_fan_value(self):
total_len = len(self.typename) + len(self.typesn) + \
len(self.typehwinfo) + len(typedevtype_t) + 8
+ rawdata_len = self._FAN_TLV_HDR_LEN + total_len + 2
+ if rawdata_len > size:
+ raise FantlvException("Generate rg tlv value failed, totallen: %d more than e2_size: %d" % (rawdata_len, size), -10)
+
bin_buffer[4] = chr(total_len >> 8)
bin_buffer[5] = chr(total_len & 0x00FF)
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
index f95164e03601..c409a4e11202 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fru.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/fru.py
@@ -1,7 +1,22 @@
#!/usr/bin/python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import collections
from datetime import datetime, timedelta
-from bitarray import bitarray
__DEBUG__ = "N"
@@ -27,17 +42,19 @@ def d_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)
+ return 0x3f & ord(value)
@staticmethod
- def minToData():
+ def minToData(endtime = None):
starttime = datetime(1996, 1, 1, 0, 0, 0)
- endtime = datetime.now()
+ if isinstance(endtime, str):
+ try:
+ endtime = datetime.strptime(endtime, "%Y-%m-%d %H:%M:%S")
+ except Exception as e:
+ d_print("Invalid endtime format, endtime: %s, errmsg: %s, used datetime.now" % (endtime, str(e)))
+ endtime = datetime.now()
+ else:
+ endtime = datetime.now()
seconds = (endtime - starttime).total_seconds()
mins = seconds // 60
m = int(round(mins))
@@ -51,12 +68,7 @@ def getTimeFormat():
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)
+ return 0xc0 | len(value)
@staticmethod
def checksum(b):
@@ -146,7 +158,7 @@ class BoardInfoArea(BaseArea):
def __str__(self):
formatstr = "version : %x\n" \
"length : %d \n" \
- "language : %x \n" \
+ "language : %d \n" \
"mfg_date : %s \n" \
"boardManufacturer : %s \n" \
"boardProductName : %s \n" \
@@ -247,8 +259,9 @@ def fruSetValue(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 language:%d" % self.language)
+
+ self.mfg_date = FruUtil.minToData(self.mfg_date)
d_print("boardInfoArea mfg_date:%x" % self.mfg_date)
self.data = chr(ord(self.boardversion)) + \
@@ -396,7 +409,7 @@ class ProductInfoArea(BaseArea):
def __str__(self):
formatstr = "version : %x\n" \
"length : %d \n" \
- "language : %x \n" \
+ "language : %d \n" \
"productManufacturer : %s \n" \
"productName : %s \n" \
"productPartModelName: %s \n" \
@@ -576,7 +589,7 @@ def fruSetValue(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)
+ d_print("product language:%d" % self.language)
self.data = chr(ord(self.areaversion)) + \
chr(self.size // 8) + chr(self.language)
@@ -928,7 +941,7 @@ def recalcuteCommonHead(self):
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)
+ raise FruException("Generate fru value failed, totallen: %d more than e2_size: %d" % (totallen, self._frusize), -2)
def recalcutebin(self):
self.bodybin = ""
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
index a90f8f8453c8..e61b982ea122 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/onietlv.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/onietlv.py
@@ -1,4 +1,20 @@
#!/usr/bin/python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import binascii
@@ -12,7 +28,7 @@ def __init__(self, message='onietlverror', code=-100):
class onie_tlv(object):
TLV_INFO_ID_STRING = "TlvInfo\x00"
- TLV_INFO_INIA_ID = "\x00\x00\x13\x11"
+ TLV_INFO_IANA_HEADER = "\x00"
TLV_INFO_VERSION = 0x01
TLV_INFO_LENGTH = 0x00
TLV_INFO_LENGTH_VALUE = 0xba
@@ -186,7 +202,7 @@ def generate_ext(self, cardid):
ret = chr(0x01) + chr(len(ret)) + ret
return ret
- def generate_value(self, _t):
+ def generate_value(self, _t, size=256):
ret = []
for i in self.TLV_INFO_ID_STRING:
ret.append(i)
@@ -195,7 +211,8 @@ def generate_value(self, _t):
ret.append(chr(self.TLV_INFO_LENGTH_VALUE))
total_len = 0
- for key in _t:
+ key_list = sorted(_t.keys())
+ for key in key_list:
x = self.getTLV_BODY(key, _t[key])
ret += x
total_len += len(x)
@@ -207,8 +224,11 @@ def generate_value(self, _t):
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):
+ if totallen > size:
+ raise OnietlvException("Generate ONIE tlv value failed, totallen: %d more than e2_size: %d" % (totallen, size), -1)
+
+ if totallen < size:
+ for left_t in range(0, size - totallen):
ret.append(chr(0x00))
return (ret, True)
@@ -236,7 +256,7 @@ def decode(self, e):
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:
+ if item["value"][0] == self.TLV_INFO_IANA_HEADER:
rt = self.decode_tlv(item["value"][4:])
else:
rt = self.decode_tlv(item["value"][0:])
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/wedge.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/wedge.py
new file mode 100755
index 000000000000..139977eccc7b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/wedge.py
@@ -0,0 +1,418 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import re
+
+class WedgeException(Exception):
+ def __init__(self, message='wedgeerror', code=-100):
+ err = 'errcode: {0} message:{1}'.format(code, message)
+ Exception.__init__(self, err)
+ self.code = code
+ self.message = message
+
+class Wedge():
+ MAGIC_HEAD_INFO = 0xfbfb
+ VERSION = 0x03
+ WEDGE_SIZE = 196
+
+ _FBW_EEPROM_F_MAGIC = 2
+ _FBW_EEPROM_F_VERSION = 1
+ _FBW_EEPROM_F_PRODUCT_NAME = 20
+ _FBW_EEPROM_F_PRODUCT_NUMBER = 8
+ _FBW_EEPROM_F_ASSEMBLY_NUMBER = 12
+ _FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER = 12
+ _FBW_EEPROM_F_FACEBOOK_PCB_NUMBER = 12
+ _FBW_EEPROM_F_ODM_PCBA_NUMBER = 13
+ _FBW_EEPROM_F_ODM_PCBA_SERIAL = 13
+ _FBW_EEPROM_F_PRODUCT_STATE = 1
+ _FBW_EEPROM_F_PRODUCT_VERSION = 1
+ _FBW_EEPROM_F_PRODUCT_SUBVERSION = 1
+ _FBW_EEPROM_F_PRODUCT_SERIAL = 13
+ _FBW_EEPROM_F_PRODUCT_ASSET = 12
+ _FBW_EEPROM_F_SYSTEM_MANUFACTURER = 8
+ _FBW_EEPROM_F_SYSTEM_MANU_DATE = 4
+ _FBW_EEPROM_F_PCB_MANUFACTURER = 8
+ _FBW_EEPROM_F_ASSEMBLED = 8
+ _FBW_EEPROM_F_LOCAL_MAC = 12
+ _FBW_EEPROM_F_EXT_MAC_BASE = 12
+ _FBW_EEPROM_F_EXT_MAC_SIZE = 2
+ _FBW_EEPROM_F_LOCATION = 20
+ _FBW_EEPROM_F_CRC8 = 1
+
+ def __init__(self):
+ self.magic = ""
+ self.fbw_version = ""
+ self.fbw_product_name = ""
+ self.fbw_product_number = ""
+ self.fbw_assembly_number = ""
+ self.fbw_facebook_pcba_number = ""
+ self.fbw_facebook_pcb_number = ""
+ self.fbw_odm_pcba_number = ""
+ self.fbw_odm_pcba_serial = ""
+ self.fbw_production_state = ""
+ self.fbw_product_version = ""
+ self.fbw_product_subversion = ""
+ self.fbw_product_serial = ""
+ self.fbw_product_asset = ""
+ self.fbw_system_manufacturer = ""
+ self.fbw_system_manufacturing_date = ""
+ self.fbw_system_manufacturing_date_show = ""
+ self.fbw_pcb_manufacturer = ""
+ self.fbw_assembled = ""
+ self.fbw_local_mac = ""
+ self.fbw_local_mac_show = ""
+ self.fbw_mac_base = ""
+ self.fbw_mac_base_show = ""
+ self.fbw_mac_size = ""
+ self.fbw_location = ""
+ self.fbw_crc8 = ""
+
+ def isValidMac(self, mac):
+ if re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$", mac):
+ return True
+ return False
+
+ def mac_addr_decode(self, origin_mac):
+ mac = origin_mac.replace("0x", "")
+ if len(mac) != 12:
+ msg = "Invalid MAC address: %s" % origin_mac
+ return False, msg
+ release_mac = ""
+ for i in range(len(mac) // 2):
+ if i == 0:
+ release_mac += mac[i * 2:i * 2 + 2]
+ else:
+ release_mac += ":" + mac[i * 2:i * 2 + 2]
+ return True, release_mac
+
+ def wedge_crc8(self, v):
+ # TBD
+ return '0x00'
+
+ def strtoarr(self, str_tmp, size):
+ if len(str_tmp) > size:
+ raise WedgeException("Wedge eeprom str:%s exceed max len: %d" % (str_tmp, size), -10)
+
+ s = []
+ for index in str_tmp:
+ s.append(index)
+
+ append_len = size - len(str_tmp)
+ if append_len > 0:
+ append_list = [chr(0x00)] * append_len
+ s.extend(append_list)
+ return s
+
+ def generate_value(self, size=256):
+ bin_buffer = [chr(0x00)] * size
+ bin_buffer[0] = chr(0xfb)
+ bin_buffer[1] = chr(0xfb)
+ bin_buffer[2] = chr(0x03)
+
+ index_start = 3
+ # Product Name
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_PRODUCT_NAME] = self.strtoarr(self.fbw_product_name,
+ self._FBW_EEPROM_F_PRODUCT_NAME)
+ index_start += self._FBW_EEPROM_F_PRODUCT_NAME
+ # Product Part Numbe
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_PRODUCT_NUMBER] = self.strtoarr(self.fbw_product_number,
+ self._FBW_EEPROM_F_PRODUCT_NUMBER)
+ index_start += self._FBW_EEPROM_F_PRODUCT_NUMBER
+
+ # System Assembly Part Number
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_ASSEMBLY_NUMBER] = self.strtoarr(self.fbw_assembly_number,
+ self._FBW_EEPROM_F_ASSEMBLY_NUMBER)
+ index_start += self._FBW_EEPROM_F_ASSEMBLY_NUMBER
+
+ # Facebook PCBA Part Number
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER] = self.strtoarr(self.fbw_facebook_pcba_number,
+ self._FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER)
+ index_start += self._FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER
+
+ # Facebook PCB Part Number
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_FACEBOOK_PCB_NUMBER] = self.strtoarr(self.fbw_facebook_pcb_number,
+ self._FBW_EEPROM_F_FACEBOOK_PCB_NUMBER)
+ index_start += self._FBW_EEPROM_F_FACEBOOK_PCB_NUMBER
+
+ # ODM PCBA Part Number
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_ODM_PCBA_NUMBER] = self.strtoarr(self.fbw_odm_pcba_number,
+ self._FBW_EEPROM_F_ODM_PCBA_NUMBER)
+ index_start += self._FBW_EEPROM_F_ODM_PCBA_NUMBER
+
+ # ODM PCBA Serial Number
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_ODM_PCBA_SERIAL] = self.strtoarr(self.fbw_odm_pcba_serial,
+ self._FBW_EEPROM_F_ODM_PCBA_SERIAL)
+ index_start += self._FBW_EEPROM_F_ODM_PCBA_SERIAL
+
+ # Product Production State
+ if self.fbw_production_state > 0xff:
+ raise WedgeException("Product Production State: %d config error, exceed 255"
+ % self.fbw_production_state, -10)
+ bin_buffer[index_start] = chr(self.fbw_production_state)
+ index_start += self._FBW_EEPROM_F_PRODUCT_STATE
+
+ # Product Version
+ if self.fbw_product_version > 0xff:
+ raise WedgeException("Product Version: %d config error, exceed 255"
+ % self.fbw_product_version, -10)
+ bin_buffer[index_start] = chr(self.fbw_product_version)
+ index_start += self._FBW_EEPROM_F_PRODUCT_VERSION
+
+ # Product Sub Version
+ if self.fbw_product_subversion > 0xff:
+ raise WedgeException("Product Sub Version: %d config error, exceed 255"
+ % self.fbw_product_subversion, -10)
+ bin_buffer[index_start] = chr(self.fbw_product_subversion)
+ index_start += self._FBW_EEPROM_F_PRODUCT_SUBVERSION
+
+ # Product Serial Number
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_PRODUCT_SERIAL] = self.strtoarr(self.fbw_product_serial, self._FBW_EEPROM_F_PRODUCT_SERIAL)
+ index_start += self._FBW_EEPROM_F_PRODUCT_SERIAL
+
+ # Product Asset Tag
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_PRODUCT_ASSET] = self.strtoarr(self.fbw_product_asset, self._FBW_EEPROM_F_PRODUCT_ASSET)
+ index_start += self._FBW_EEPROM_F_PRODUCT_ASSET
+
+ # System Manufacturer
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_SYSTEM_MANUFACTURER] = self.strtoarr(self.fbw_system_manufacturer, self._FBW_EEPROM_F_SYSTEM_MANUFACTURER)
+ index_start += self._FBW_EEPROM_F_SYSTEM_MANUFACTURER
+
+ # System Manufacturing Date
+ if (len(self.fbw_system_manufacturing_date) != 8):
+ raise WedgeException("System Manufacturing Date config error, value: %s"
+ % self.fbw_system_manufacturing_date, -10)
+
+ year = int(self.fbw_system_manufacturing_date[0:4])
+ month = int(self.fbw_system_manufacturing_date[4:6])
+ day = int(self.fbw_system_manufacturing_date[6:8])
+ if month < 1 or month > 12 or day < 1 or day > 31:
+ raise WedgeException("System Manufacturing Date config error, value: %s"
+ % self.fbw_system_manufacturing_date, -10)
+ bin_buffer[index_start] = chr(year & 0xff)
+ bin_buffer[index_start + 1] = chr((year & 0xff00) >> 8)
+ bin_buffer[index_start + 2] = chr(month)
+ bin_buffer[index_start + 3] = chr(day)
+ index_start += self._FBW_EEPROM_F_SYSTEM_MANU_DATE
+
+ # PCB Manufacturer
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_PCB_MANUFACTURER] = self.strtoarr(self.fbw_pcb_manufacturer,
+ self._FBW_EEPROM_F_PCB_MANUFACTURER)
+ index_start += self._FBW_EEPROM_F_PCB_MANUFACTURER
+
+ # Assembled At
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_ASSEMBLED] = self.strtoarr(self.fbw_assembled,
+ self._FBW_EEPROM_F_ASSEMBLED)
+ index_start += self._FBW_EEPROM_F_ASSEMBLED
+
+ # Local MAC Address
+ status, mac = self.mac_addr_decode(self.fbw_local_mac)
+ if self.isValidMac(mac) is False:
+ msg = "Invalid Local MAC Address: %s" % self.fbw_local_mac
+ raise WedgeException(msg , -10)
+
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_LOCAL_MAC] = self.strtoarr(self.fbw_local_mac, self._FBW_EEPROM_F_LOCAL_MAC)
+ index_start += self._FBW_EEPROM_F_LOCAL_MAC
+ # Extended MAC Address
+ status, mac = self.mac_addr_decode(self.fbw_mac_base)
+ if self.isValidMac(mac) is False:
+ msg = "Invalid Extended MAC Address: %s" % self.fbw_mac_base
+ raise WedgeException(msg , -10)
+
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_EXT_MAC_BASE] = self.strtoarr(self.fbw_mac_base, self._FBW_EEPROM_F_EXT_MAC_BASE)
+ index_start += self._FBW_EEPROM_F_EXT_MAC_BASE
+
+ # Extended MAC Address Size
+ if self.fbw_mac_size > 0xffff:
+ raise WedgeException("Extended MAC Address Size: %d config error, exceed 65535"
+ % self.fbw_mac_size, -10)
+ bin_buffer[index_start] = chr(self.fbw_mac_size & 0xff)
+ bin_buffer[index_start + 1] = chr((self.fbw_mac_size & 0xff00) >> 8)
+ index_start += self._FBW_EEPROM_F_EXT_MAC_SIZE
+
+ # Location on Fabric
+ bin_buffer[index_start: index_start + self._FBW_EEPROM_F_LOCATION] = self.strtoarr(self.fbw_location,
+ self._FBW_EEPROM_F_LOCATION)
+ index_start += self._FBW_EEPROM_F_LOCATION
+
+ # CRC8
+ bin_buffer[index_start] = chr(0x00)
+ index_start += self._FBW_EEPROM_F_CRC8
+ return bin_buffer
+
+ def decode(self, e2):
+ # header check
+ e2_index = 0
+ head = ord(e2[0]) | (ord(e2[1]) << 8)
+ if head != self.MAGIC_HEAD_INFO:
+ raise WedgeException("Wedge eeprom head info error, not Wedge eeprom type, head:0x%04x" % head, -10)
+ self.magic = "0x%04x" % self.MAGIC_HEAD_INFO
+ e2_index += self._FBW_EEPROM_F_MAGIC
+
+ # E2 format version check
+ if ord(e2[e2_index]) != self.VERSION:
+ raise WedgeException("Wedge eeprom version: 0x%02x, not V3 format" % ord(e2[e2_index]), -10)
+ self.fbw_version = self.VERSION
+ e2_index += self._FBW_EEPROM_F_VERSION
+
+ # crc
+ self.fbw_crc8 = ord(e2[self.WEDGE_SIZE-1])
+
+ # Product Name
+ self.fbw_product_name = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_PRODUCT_NAME])
+ e2_index += self._FBW_EEPROM_F_PRODUCT_NAME
+
+ # Product Part Numbe
+ self.fbw_product_number = "%s" % e2[e2_index:e2_index+self._FBW_EEPROM_F_PRODUCT_NUMBER]
+ #self.fbw_product_number = "%s-%s" % (e2[e2_index:e2_index+2], e2[e2_index + 2: e2_index + 8])
+ e2_index += self._FBW_EEPROM_F_PRODUCT_NUMBER
+
+ # System Assembly Part Number
+ self.fbw_assembly_number = "%s" % e2[e2_index:e2_index+self._FBW_EEPROM_F_ASSEMBLY_NUMBER]
+ #self.fbw_assembly_number = "%s-%s-%s" % (e2[e2_index:e2_index+3], e2[e2_index+3:e2_index+10], e2[e2_index+10:e2_index+12])
+ e2_index += self._FBW_EEPROM_F_ASSEMBLY_NUMBER
+
+ # Facebook PCBA Part Number
+ self.fbw_facebook_pcba_number = "%s" % e2[e2_index:e2_index+self._FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER]
+ #self.fbw_facebook_pcba_number = "%s-%s-%s" % (e2[e2_index:e2_index+3], e2[e2_index+3:e2_index+10], e2[e2_index+10:e2_index+12])
+ e2_index += self._FBW_EEPROM_F_FACEBOOK_PCBA_NUMBER
+
+ # Facebook PCB Part Number
+ self.fbw_facebook_pcb_number ="%s" % e2[e2_index:e2_index+self._FBW_EEPROM_F_FACEBOOK_PCB_NUMBER]
+ #self.fbw_facebook_pcb_number = "%s-%s-%s" % (e2[e2_index:e2_index+3], e2[e2_index+3:e2_index+10], e2[e2_index+10:e2_index+12])
+ e2_index += self._FBW_EEPROM_F_FACEBOOK_PCB_NUMBER
+
+ # ODM PCBA Part Number
+ self.fbw_odm_pcba_number = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_ODM_PCBA_NUMBER])
+ e2_index += self._FBW_EEPROM_F_ODM_PCBA_NUMBER
+
+ # ODM PCBA Serial Number
+ self.fbw_odm_pcba_serial = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_ODM_PCBA_SERIAL])
+ e2_index += self._FBW_EEPROM_F_ODM_PCBA_SERIAL
+
+ # Product Production State
+ self.fbw_production_state = (ord(e2[e2_index]))
+ e2_index += self._FBW_EEPROM_F_PRODUCT_STATE
+
+ # Product Version
+ self.fbw_product_version = (ord(e2[e2_index]))
+ e2_index += self._FBW_EEPROM_F_PRODUCT_VERSION
+
+ # Product Version
+ self.fbw_product_subversion = (ord(e2[e2_index]))
+ e2_index += self._FBW_EEPROM_F_PRODUCT_SUBVERSION
+
+ # Product Serial Number
+ self.fbw_product_serial = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_PRODUCT_SERIAL])
+ e2_index += self._FBW_EEPROM_F_PRODUCT_SERIAL
+
+ # Product Asset Tag
+ self.fbw_product_asset = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_PRODUCT_ASSET])
+ e2_index += self._FBW_EEPROM_F_PRODUCT_ASSET
+
+ # System Manufacturer
+ self.fbw_system_manufacturer = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_SYSTEM_MANUFACTURER])
+ e2_index += self._FBW_EEPROM_F_SYSTEM_MANUFACTURER
+
+ # System Manufacturing Date
+ year = ord(e2[e2_index]) | (ord(e2[e2_index + 1]) << 8)
+ month = ord(e2[e2_index + 2])
+ day = ord(e2[e2_index + 3])
+ self.fbw_system_manufacturing_date = "%04d%02d%02d" % (year, month, day)
+ self.fbw_system_manufacturing_date_show = "%02d-%02d-%04d" % (month, day, year)
+ e2_index += self._FBW_EEPROM_F_SYSTEM_MANU_DATE
+
+ # PCB Manufacturer
+ self.fbw_pcb_manufacturer = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_PCB_MANUFACTURER])
+ e2_index += self._FBW_EEPROM_F_PCB_MANUFACTURER
+
+ # Assembled At
+ self.fbw_assembled = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_ASSEMBLED])
+ e2_index += self._FBW_EEPROM_F_ASSEMBLED
+
+ # Local MAC Address
+ self.fbw_local_mac = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_LOCAL_MAC])
+ status, mac = self.mac_addr_decode(self.fbw_local_mac)
+ if status is False:
+ raise WedgeException("Wedge eeprom decode local MAC error, msg: %s" % mac, -10)
+ self.fbw_local_mac_show = mac.upper()
+ e2_index += self._FBW_EEPROM_F_LOCAL_MAC
+
+ # Extended MAC Address
+ self.fbw_mac_base = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_EXT_MAC_BASE])
+ status, mac = self.mac_addr_decode(self.fbw_mac_base)
+ if status is False:
+ raise WedgeException("Wedge eeprom decode local MAC error, msg: %s" % mac, -10)
+ self.fbw_mac_base_show = mac.upper()
+ e2_index += self._FBW_EEPROM_F_EXT_MAC_BASE
+
+ # Extended MAC Address Size
+ mac_size = ord(e2[e2_index]) | (ord(e2[e2_index + 1]) << 8)
+ self.fbw_mac_size = mac_size
+ e2_index += self._FBW_EEPROM_F_EXT_MAC_SIZE
+
+ # Location on Fabric
+ self.fbw_location = "%s" % (e2[e2_index:e2_index + self._FBW_EEPROM_F_LOCATION])
+ e2_index += self._FBW_EEPROM_F_LOCATION
+ return
+
+
+ def __str__(self):
+ formatstr = "Version : %d \n" \
+ "Product Name : %s \n" \
+ "Product Part Number : %s \n" \
+ "System Assembly Part Number : %s \n" \
+ "Facebook PCBA Part Number : %s \n" \
+ "Facebook PCB Part Number : %s \n" \
+ "ODM PCBA Part Number : %s \n" \
+ "ODM PCBA Serial Number : %s \n" \
+ "Product Production State : %d \n" \
+ "Product Version : %d \n" \
+ "Product Sub-Version : %d \n" \
+ "Product Serial Number : %s \n" \
+ "Product Asset Tag : %s \n" \
+ "System Manufacturer : %s \n" \
+ "System Manufacturing Date : %s \n" \
+ "PCB Manufacturer : %s \n" \
+ "Assembled At : %s \n" \
+ "Local MAC : %s \n" \
+ "Extended MAC Base : %s \n" \
+ "Extended MAC Address Size : %d \n" \
+ "Location on Fabric : %s \n" \
+ "CRC8 : 0x%02x \n"
+ str_tmp = formatstr % (self.fbw_version,
+ self.fbw_product_name,
+ self.fbw_product_number,
+ self.fbw_assembly_number,
+ self.fbw_facebook_pcba_number,
+ self.fbw_facebook_pcb_number,
+ self.fbw_odm_pcba_number,
+ self.fbw_odm_pcba_serial,
+ self.fbw_production_state,
+ self.fbw_product_version,
+ self.fbw_product_subversion,
+ self.fbw_product_serial,
+ self.fbw_product_asset,
+ self.fbw_system_manufacturer,
+ self.fbw_system_manufacturing_date_show,
+ self.fbw_pcb_manufacturer,
+ self.fbw_assembled,
+ self.fbw_local_mac_show,
+ self.fbw_mac_base_show,
+ self.fbw_mac_size,
+ self.fbw_location,
+ self.fbw_crc8)
+ return str_tmp.replace("\x00","")
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/wedge_v5.py b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/wedge_v5.py
new file mode 100755
index 000000000000..4d42865f619b
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/eepromutil/wedge_v5.py
@@ -0,0 +1,591 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import re
+
+class WedgeException(Exception):
+ def __init__(self, message='wedgeerror', code=-100):
+ err = 'errcode: {0} message:{1}'.format(code, message)
+ Exception.__init__(self, err)
+ self.code = code
+ self.message = message
+
+class WedgeV5():
+ MAGIC_HEAD_INFO = 0xfbfb
+ VERSION = 0x05
+
+ FBWV5_PRODUCT_NAME = 0x01
+ FBWV5_PRODUCT_PART_NUMBER = 0x02
+ FBWV5_ASSEMBLY_PART_NUMBER = 0x03
+ FBWV5_ASSEMBLY_PART_NUMBER_LEN = 8
+ FBWV5_META_PCBA_PART_NUMBER = 0x04
+ FBWV5_META_PCBA_PART_NUMBER_LEN = 12
+ FBWV5_META_PCB_PART_NUMBER = 0x05
+ FBWV5_META_PCB_PART_NUMBER_LEN = 12
+ FBWV5_ODM_PCBA_PART_NUMBER = 0x06
+ FBWV5_ODM_PCBA_SERIAL_NUMBER = 0x07
+ FBWV5_PRODUCT_PRODUCTION_STATE = 0x08
+ FBWV5_PRODUCT_PRODUCTION_STATE_LEN = 1
+ FBWV5_PRODUCT_VERSION = 0x09
+ FBWV5_PRODUCT_VERSION_LEN = 1
+ FBWV5_PRODUCT_SUB_VERSION = 0x0A
+ FBWV5_PRODUCT_SUB_VERSION_LEN = 1
+ FBWV5_PRODUCT_SERIAL_NUMBER = 0x0B
+ FBWV5_SYSTEM_MANUFACTURER = 0x0C
+ FBWV5_SYSTEM_MANUFACTURING_DATE = 0x0D
+ FBWV5_SYSTEM_MANUFACTURING_DATE_LEN = 8
+ FBWV5_PCB_MANUFACTURER = 0x0E
+ FBWV5_ASSEMBLED_AT = 0x0F
+ FBWV5_E2_LOCATION_ON_FABRIC = 0x10
+ FBWV5_X86_CPU_MAC = 0x11
+ FBWV5_X86_CPU_MAC_LEN = 8
+ FBWV5_BMC_MAC = 0x12
+ FBWV5_BMC_MAC_LEN = 8
+ FBWV5_SWITCH_ASIC_MAC = 0x13
+ FBWV5_SWITCH_ASIC_MAC_LEN = 8
+ FBWV5_META_RESERVED_MAC = 0x14
+ FBWV5_META_RESERVED_MAC_LEN = 8
+ FBWV5_CRC16 = 0xFA
+
+
+ @property
+ def product_name(self):
+ return self._ProductName
+
+ @property
+ def product_part_number(self):
+ return self._ProductPartNumber
+
+ @property
+ def assembly_part_number(self):
+ return self._AssemblyPartNumber
+
+ @property
+ def meta_pcba_part_number(self):
+ return self._MetaPCBAPartNumber
+
+ @property
+ def meta_pcb_part_number(self):
+ return self._MetaPCBPartNumber
+
+ @property
+ def odm_pcba_part_number(self):
+ return self._ODMPCBAPartNumber
+
+ @property
+ def odm_pcba_serial_number(self):
+ return self._ODMPCBASerialNumber
+
+ @property
+ def product_production_state(self):
+ return self._ProductProductionState
+
+ @property
+ def product_version(self):
+ return self._ProductVersion
+
+ @property
+ def product_sub_version(self):
+ return self._ProductSubVersion
+
+ @property
+ def product_serial_number(self):
+ return self._ProductSerialNumber
+
+ @property
+ def system_manufacturer(self):
+ return self._SystemManufacturer
+
+ @property
+ def system_manufacturing_date(self):
+ return self._SystemManufacturingDate
+
+ @property
+ def pcb_manufacturer(self):
+ return self._PCBManufacturer
+
+ @property
+ def assembled_at(self):
+ return self._AssembledAt
+
+ @property
+ def e2_location_on_fabric(self):
+ return self._E2LocationOnFabric
+
+ @property
+ def x86_cpu_mac(self):
+ return self._X86_CPU_MAC
+
+ @property
+ def x86_cpu_mac_size(self):
+ return self._X86_CPU_MAC_SIZE
+
+ @property
+ def bmc_mac(self):
+ return self._BMC_MAC
+
+ @property
+ def bmc_mac_size(self):
+ return self._BMC_MAC_SIZE
+
+ @property
+ def switch_asic_mac(self):
+ return self._SWITCH_ASIC_MAC
+
+ @property
+ def switch_asic_mac_size(self):
+ return self._SWITCH_ASIC_MAC_SIZE
+
+ @property
+ def meta_reserved_mac(self):
+ return self._MetaReservedMAC
+
+ @property
+ def meta_reserved_mac_size(self):
+ return self._MetaReservedMAC_SIZE
+
+ @property
+ def crc16(self):
+ return self._crc16
+
+
+ def __init__(self):
+ self._ProductName = ""
+ self._ProductPartNumber = ""
+ self._AssemblyPartNumber = ""
+ self._MetaPCBAPartNumber = ""
+ self._MetaPCBPartNumber = ""
+ self._ODMPCBAPartNumber = ""
+ self._ODMPCBASerialNumber = ""
+ self._ProductProductionState = ""
+ self._ProductVersion = ""
+ self._ProductSubVersion = ""
+ self._ProductSerialNumber = ""
+ self._SystemManufacturer = ""
+ self._SystemManufacturingDate = ""
+ self._PCBManufacturer = ""
+ self._AssembledAt = ""
+ self._E2LocationOnFabric = ""
+ self._X86_CPU_MAC = ""
+ self._X86_CPU_MAC_SIZE = ""
+ self._BMC_MAC = ""
+ self._BMC_MAC_SIZE = ""
+ self._SWITCH_ASIC_MAC = ""
+ self._SWITCH_ASIC_MAC_SIZE = ""
+ self._MetaReservedMAC = ""
+ self._MetaReservedMAC_SIZE = ""
+ self._crc16 = ""
+
+ def crc_ccitt(self, data, crc_init=0xFFFF, poly=0x1021):
+ '''
+ CRC-16-CCITT Algorithm
+ '''
+
+ data_array = bytearray()
+ for x in data:
+ data_array.append(ord(x))
+
+ crc = crc_init
+ for byte in data_array:
+ crc ^= byte << 8
+ for _ in range(8):
+ if crc & 0x8000:
+ crc = (crc << 1) ^ poly
+ else:
+ crc <<= 1
+ crc &= 0xFFFF
+
+ return '0x%04X' % (crc & 0xFFFF)
+
+
+ def check_mac_addr(self, mac):
+ if re.match(r"^\s*([0-9a-fA-F]{2,2}:){5,5}[0-9a-fA-F]{2,2}\s*$", mac):
+ return True
+ return False
+
+ def decoce_mac_and_size(self, value):
+ mac_addr = ":".join(['%02X' % ord(T) for T in value[0:6]]).upper()
+ ret = self.check_mac_addr(mac_addr)
+ if ret is False:
+ return False, "Invalid MAC address: [%s]" % mac_addr
+
+ mac_size = ((ord(value[6]) << 8) | ord(value[7]))
+ if mac_size == 0:
+ return False, "Invalid MAC address size: %d" % mac_size
+ return True, ""
+
+ def getTLV_BODY(self, tlv_type, value):
+ x = []
+ temp_t = None
+ if tlv_type == self.FBWV5_ASSEMBLY_PART_NUMBER and len(value) != self.FBWV5_ASSEMBLY_PART_NUMBER_LEN:
+ if len(value) > self.FBWV5_ASSEMBLY_PART_NUMBER_LEN:
+ raise WedgeException("Invalid System Assembly Part Number length. value: %s, length: %d, length must less than %d" %
+ (value, len(value), self.FBWV5_ASSEMBLY_PART_NUMBER_LEN), -1)
+ temp_list = list(value) + [chr(0x00)] * (self.FBWV5_ASSEMBLY_PART_NUMBER_LEN - len(value))
+ temp_t = ''.join(temp_list)
+
+ if tlv_type == self.FBWV5_META_PCBA_PART_NUMBER and len(value) != self.FBWV5_META_PCBA_PART_NUMBER_LEN:
+ if len(value) > self.FBWV5_META_PCBA_PART_NUMBER_LEN:
+ raise WedgeException("Invalid Meta PCBA Part Number length. value: %s, length: %d, length must be %d" %
+ (value, len(value), self.FBWV5_META_PCBA_PART_NUMBER_LEN), -1)
+ temp_list = list(value) + [chr(0x00)] * (self.FBWV5_META_PCBA_PART_NUMBER_LEN - len(value))
+ temp_t = ''.join(temp_list)
+
+
+ if tlv_type == self.FBWV5_META_PCB_PART_NUMBER and len(value) != self.FBWV5_META_PCB_PART_NUMBER_LEN:
+ if len(value) > self.FBWV5_META_PCB_PART_NUMBER_LEN:
+ raise WedgeException("Invalid Meta PCB Part Number length. value: %s, length: %d, length must be %d" %
+ (value, len(value), self.FBWV5_META_PCB_PART_NUMBER_LEN), -1)
+ temp_list = list(value) + [chr(0x00)] * (self.FBWV5_META_PCB_PART_NUMBER_LEN - len(value))
+ temp_t = ''.join(temp_list)
+
+ if (tlv_type == self.FBWV5_PRODUCT_PRODUCTION_STATE
+ or tlv_type == self.FBWV5_PRODUCT_VERSION
+ or tlv_type == self.FBWV5_PRODUCT_SUB_VERSION):
+ if not isinstance(value, int) or value > 0xff or value < 0:
+ raise WedgeException("Invalid Wedge EEPROM Format V5 Tlv type: %d, value: %s" %
+ (tlv_type, value), -1)
+ temp_t = chr(value)
+
+ if tlv_type == self.FBWV5_SYSTEM_MANUFACTURING_DATE and len(value) != self.FBWV5_SYSTEM_MANUFACTURING_DATE_LEN:
+ raise WedgeException("Invalid System Manufacturing Date. value: %s, length: %d, format must YYYYMMDD"
+ % (value, len(value)), -1)
+
+ if tlv_type == self.FBWV5_X86_CPU_MAC:
+ if len(value) != self.FBWV5_X86_CPU_MAC_LEN:
+ raise WedgeException("Invalid X86 CPU MAC length: %d, must be %d"
+ % (len(value), self.FBWV5_X86_CPU_MAC_LEN), -1)
+ status, msg = self.decoce_mac_and_size(value)
+ if status is False:
+ raise WedgeException("Decode X86 CPU MAC failed, msg: %s" % (value, msg), -1)
+
+ if tlv_type == self.FBWV5_BMC_MAC:
+ if len(value) != self.FBWV5_BMC_MAC_LEN:
+ raise WedgeException("Invalid BMC MAC length: %d, must be %d"
+ % (len(value), self.FBWV5_BMC_MAC_LEN), -1)
+ status, msg = self.decoce_mac_and_size(value)
+ if status is False:
+ raise WedgeException("Decode BMC MAC failed, msg: %s" % (value, msg), -1)
+
+ if tlv_type == self.FBWV5_SWITCH_ASIC_MAC:
+ if len(value) != self.FBWV5_SWITCH_ASIC_MAC_LEN:
+ raise WedgeException("Invalid Switch ASIC MAC length: %d, must be %d"
+ % (len(value), self.FBWV5_SWITCH_ASIC_MAC_LEN), -1)
+ status, msg = self.decoce_mac_and_size(value)
+ if status is False:
+ raise WedgeException("Decode Switch ASIC MAC failed, msg: %s" % (value, msg), -1)
+
+ if tlv_type == self.FBWV5_META_RESERVED_MAC:
+ if len(value) != self.FBWV5_META_RESERVED_MAC_LEN:
+ raise WedgeException("Invalid META Reserved MAC length: %d, must be %d"
+ % (len(value), self.FBWV5_META_RESERVED_MAC_LEN), -1)
+ status, msg = self.decoce_mac_and_size(value)
+ if status is False:
+ raise WedgeException("Decode META Reserved MAC failed, msg: %s" % (value, msg), -1)
+
+ if temp_t is None:
+ 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_value(self, _t, size=256):
+ ret = []
+ ret.append(chr(0xfb))
+ ret.append(chr(0xfb))
+ ret.append(chr(self.VERSION))
+ ret.append(chr(0xff))
+
+ key_list = sorted(_t.keys())
+ for key in key_list:
+ x = self.getTLV_BODY(key, _t[key])
+ ret += x
+
+ crc16_str = self.crc_ccitt(ret)
+ crc16_val = int(crc16_str, 16)
+
+ ret.append(chr(self.FBWV5_CRC16))
+ ret.append(chr(0x02))
+ ret.append(chr((crc16_val >> 8) & 0xff))
+ ret.append(chr((crc16_val & 0xff)))
+
+ totallen = len(ret)
+ if (totallen > size):
+ raise WedgeException("Generate Wedge EEPROM Format V5 failed, totallen: %d more than e2_size: %d"
+ % (totallen, size), -1)
+ if (totallen < size):
+ for left_t in range(0, size - totallen):
+ ret.append(chr(0x00))
+ return ret
+
+ def decoder(self, t):
+ ret = []
+ if ord(t[0]) == self.FBWV5_PRODUCT_NAME:
+ name = "Product Name"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._ProductName = value
+ elif ord(t[0]) == self.FBWV5_PRODUCT_PART_NUMBER:
+ name = "Product Part Number"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._ProductPartNumber = value
+ elif ord(t[0]) == self.FBWV5_ASSEMBLY_PART_NUMBER:
+ name = "System Assembly Part Number"
+ _len = ord(t[1])
+ if _len != self.FBWV5_ASSEMBLY_PART_NUMBER_LEN:
+ raise WedgeException("Invalid System Assembly Part Number len: %d" % _len, -1)
+ value = t[2:2 + ord(t[1])]
+ self._AssemblyPartNumber = value
+ elif ord(t[0]) == self.FBWV5_META_PCBA_PART_NUMBER:
+ name = "Meta PCBA Part Number"
+ _len = ord(t[1])
+ if _len != self.FBWV5_META_PCBA_PART_NUMBER_LEN:
+ raise WedgeException("Invalid Meta PCBA Part Number len: %d" % _len, -1)
+ value = t[2:2 + ord(t[1])]
+ self._MetaPCBAPartNumber = value
+ elif ord(t[0]) == self.FBWV5_META_PCB_PART_NUMBER:
+ name = "Meta PCB Part Number"
+ _len = ord(t[1])
+ if _len != self.FBWV5_META_PCB_PART_NUMBER_LEN:
+ raise WedgeException("Invalid Meta PCB Part Number len: %d" % _len, -1)
+ value = t[2:2 + ord(t[1])]
+ self._MetaPCBPartNumber = value
+ elif ord(t[0]) == self.FBWV5_ODM_PCBA_PART_NUMBER:
+ name = "ODM/JDM PCBA Part Number"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._ODMPCBAPartNumber = value
+ elif ord(t[0]) == self.FBWV5_ODM_PCBA_SERIAL_NUMBER:
+ name = "ODM/JDM PCBA Serial Number"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._ODMPCBASerialNumber = value
+ elif ord(t[0]) == self.FBWV5_PRODUCT_PRODUCTION_STATE:
+ name = "Product Production State"
+ _len = ord(t[1])
+ if _len != self.FBWV5_PRODUCT_PRODUCTION_STATE_LEN:
+ raise WedgeException("Invalid Product Production State len: %d" % _len, -1)
+ value = ord(t[2])
+ self._ProductProductionState = value
+ elif ord(t[0]) == self.FBWV5_PRODUCT_VERSION:
+ name = "Product Version"
+ _len = ord(t[1])
+ if _len != self.FBWV5_PRODUCT_VERSION_LEN:
+ raise WedgeException("Invalid Product Version len: %d" % _len, -1)
+ value = ord(t[2])
+ self._ProductVersion = value
+ elif ord(t[0]) == self.FBWV5_PRODUCT_SUB_VERSION:
+ name = "Product Sub-Version"
+ _len = ord(t[1])
+ if _len != self.FBWV5_PRODUCT_SUB_VERSION_LEN:
+ raise WedgeException("Invalid Product Sub-Version len: %d" % _len, -1)
+ value = ord(t[2])
+ self._ProductSubVersion = value
+ elif ord(t[0]) == self.FBWV5_PRODUCT_SERIAL_NUMBER:
+ name = "Product Serial Number"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._ProductSerialNumber = value
+ elif ord(t[0]) == self.FBWV5_SYSTEM_MANUFACTURER:
+ name = "System Manufacturer"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._SystemManufacturer = value
+ elif ord(t[0]) == self.FBWV5_SYSTEM_MANUFACTURING_DATE:
+ name = "System Manufacturing Date"
+ _len = ord(t[1])
+ if _len != self.FBWV5_SYSTEM_MANUFACTURING_DATE_LEN:
+ raise WedgeException("Invalid System Manufacturing Date len: %d" % _len, -1)
+ value = t[2:2 + ord(t[1])]
+ self._SystemManufacturingDate = value
+ elif ord(t[0]) == self.FBWV5_PCB_MANUFACTURER:
+ name = "PCB Manufacturer"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._PCBManufacturer = value
+ elif ord(t[0]) == self.FBWV5_ASSEMBLED_AT:
+ name = "Assembled at"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._AssembledAt = value
+ elif ord(t[0]) == self.FBWV5_E2_LOCATION_ON_FABRIC:
+ name = "EEPROM location on Fabric"
+ _len = ord(t[1])
+ value = t[2:2 + ord(t[1])]
+ self._E2LocationOnFabric = value
+ elif ord(t[0]) == self.FBWV5_X86_CPU_MAC:
+ name = "X86 CPU MAC Base"
+ _len = ord(t[1])
+ if _len != self.FBWV5_X86_CPU_MAC_LEN:
+ raise WedgeException("Invalid X86 CPU MAC Base len: %d" % _len, -1)
+ value = ":".join(['%02X' % ord(T) for T in t[2:8]]).upper()
+ self._X86_CPU_MAC = value
+ ret.append({"name": name, "code": ord(t[0]), "value": value, "lens": 6})
+ # X86 CPU MAC Address Size
+ name = "X86 CPU MAC Address Size"
+ _len = 2
+ value = ((ord(t[8]) << 8) | ord(t[9]))
+ self._X86_CPU_MAC_SIZE = value
+ elif ord(t[0]) == self.FBWV5_BMC_MAC:
+ name = "BMC MAC Base"
+ _len = ord(t[1])
+ if _len != self.FBWV5_BMC_MAC_LEN:
+ raise WedgeException("Invalid BMC MAC Base len: %d" % _len, -1)
+ value = ":".join(['%02X' % ord(T) for T in t[2:8]]).upper()
+ self._BMC_MAC = value
+ ret.append({"name": name, "code": ord(t[0]), "value": value, "lens": 6})
+ # BMC MAC Address Size
+ name = "BMC MAC Address Size"
+ _len = 2
+ value = ((ord(t[8]) << 8) | ord(t[9]))
+ self._BMC_MAC_SIZE = value
+ elif ord(t[0]) == self.FBWV5_SWITCH_ASIC_MAC:
+ name = "Switch ASIC MAC Base"
+ _len = ord(t[1])
+ if _len != self.FBWV5_SWITCH_ASIC_MAC_LEN:
+ raise WedgeException("Invalid Switch ASIC MAC Base len: %d" % _len, -1)
+ value = ":".join(['%02X' % ord(T) for T in t[2:8]]).upper()
+ self._SWITCH_ASIC_MAC = value
+ ret.append({"name": name, "code": ord(t[0]), "value": value, "lens": 6})
+ # Switch ASIC MAC Address Size
+ name = "Switch ASIC MAC Address Size"
+ _len = 2
+ value = ((ord(t[8]) << 8) | ord(t[9]))
+ self._SWITCH_ASIC_MAC_SIZE = value
+ elif ord(t[0]) == self.FBWV5_META_RESERVED_MAC:
+ name = "META Reserved MAC Base"
+ _len = ord(t[1])
+ if _len != self.FBWV5_META_RESERVED_MAC_LEN:
+ raise WedgeException("Invalid META Reserved MAC Base len: %d" % _len, -1)
+ value = ":".join(['%02X' % ord(T) for T in t[2:8]]).upper()
+ self._MetaReservedMAC = value
+ ret.append({"name": name, "code": ord(t[0]), "value": value, "lens": 6})
+ # META Reserved MAC Address Size
+ name = "META Reserved MAC Address Size"
+ _len = 2
+ value = ((ord(t[8]) << 8) | ord(t[9]))
+ self._MetaReservedMAC_SIZE = value
+ elif ord(t[0]) == self.FBWV5_CRC16 and len(t) == 4:
+ name = "CRC16"
+ _len = ord(t[1])
+ value = "0x%04X" % ((ord(t[2]) << 8) | (ord(t[3])))
+ self._crc16 = value
+ else:
+ name = "Unknown"
+ _len = ord(t[1])
+ value = ""
+ for c in t[2:2 + ord(t[1])]:
+ value += "0x%02X " % (ord(c),)
+ raise WedgeException("Unknown Wedge EEPROM Format V5 TLV type: 0x%02x, len: %d, value: %s" % (ord(t[0]), ord(t[1]), value), -1)
+ ret.append({"name": name, "code": ord(t[0]), "value": value, "lens": _len})
+ return ret
+
+
+ def decode_tlv(self, e2):
+ tlv_index = 0
+ tlv_end = len(e2)
+ ret = []
+ while tlv_index < tlv_end:
+ rt = self.decoder(e2[tlv_index:tlv_index + 2 + ord(e2[tlv_index + 1])])
+ ret.extend(rt)
+ if ord(e2[tlv_index]) == self.FBWV5_CRC16:
+ break
+ tlv_index += ord(e2[tlv_index + 1]) + 2
+ return ret, tlv_index
+
+ def decode(self, e2):
+ e2_index = 0
+ head = ord(e2[0]) | (ord(e2[1]) << 8)
+ if head != self.MAGIC_HEAD_INFO:
+ raise WedgeException("Wedge eeprom head info error, not Wedge eeprom type, head:0x%04x" % head, -10)
+ e2_index += 2
+
+ # E2 Version check
+ if ord(e2[e2_index]) != self.VERSION:
+ raise WedgeException("Wedge eeprom version: 0x%02x, not V5 format" % ord(e2[e2_index]), -10)
+ e2_index += 1
+
+ # one byte Reserved
+ e2_index += 1
+
+ ret, tlv_data_len = self.decode_tlv(e2[e2_index:])
+
+ # check crc
+ e2_crc_data_len = tlv_data_len + 4 # two byte Magic word + one byte Format Version + one byte Reserved
+
+ crc_calc = self.crc_ccitt(e2[0:e2_crc_data_len])
+ crc_read = self.crc16
+ if crc_calc != crc_read:
+ print("Wedge EEPROM Format V5 crc error, calc value: %s, read value: %s" % (crc_calc, crc_read), -1)
+
+ return ret
+
+ def __str__(self):
+ formatstr = "Product Name : %s \n" \
+ "Product Part Number : %s \n" \
+ "System Assembly Part Number : %s \n" \
+ "Meta PCBA Part Number : %s \n" \
+ "Meta PCB Part Number : %s \n" \
+ "ODM/JDM PCBA Part Number : %s \n" \
+ "ODM/JDM PCBA Serial Number : %s \n" \
+ "Product Production State : %s \n" \
+ "Product Version : %s \n" \
+ "Product Sub-Version : %s \n" \
+ "Product Serial Number : %s \n" \
+ "System Manufacturer : %s \n" \
+ "System Manufacturing Date : %s \n" \
+ "PCB Manufacturer : %s \n" \
+ "Assembled at : %s \n" \
+ "EEPROM location on Fabric : %s \n" \
+ "X86 CPU MAC Base : %s \n" \
+ "X86 CPU MAC Address Size : %s \n" \
+ "BMC MAC Base : %s \n" \
+ "BMC MAC Address Size : %s \n" \
+ "Switch ASIC MAC Base : %s \n" \
+ "Switch ASIC MAC Address Size : %s \n" \
+ "META Reserved MAC Base : %s \n" \
+ "META Reserved MAC Address Size : %s \n" \
+ "CRC16 : %s \n"
+ return formatstr % (self.product_name,
+ self.product_part_number,
+ self.assembly_part_number,
+ self.meta_pcba_part_number,
+ self.meta_pcb_part_number,
+ self.odm_pcba_part_number,
+ self.odm_pcba_serial_number,
+ self.product_production_state,
+ self.product_version,
+ self.product_sub_version,
+ self.product_serial_number,
+ self.system_manufacturer,
+ self.system_manufacturing_date,
+ self.pcb_manufacturer,
+ self.assembled_at,
+ self.e2_location_on_fabric,
+ self.x86_cpu_mac,
+ self.x86_cpu_mac_size,
+ self.bmc_mac,
+ self.bmc_mac_size,
+ self.switch_asic_mac,
+ self.switch_asic_mac_size,
+ self.meta_reserved_mac,
+ self.meta_reserved_mac_size,
+ self.crc16)
\ No newline at end of file
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
index abf0ecf97d6b..12f9aa881daf 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# baseutil.py
-# Python implementation of the Class baseutil
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import importlib.machinery
import os
import syslog
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
index 767d6da34ba9..ea1ef4930a15 100644
--- 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
@@ -1,21 +1,31 @@
#!/usr/bin/env python3
-#######################################################
#
-# chassisbase.py
-# Python implementation of the Class chassisbase
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+import os
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.temp import temp, temp_s3ip
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
-
+from plat_hal.osutil import osutil
class chassisbase(object):
__onie_e2_list = []
@@ -89,6 +99,52 @@ def __init__(self, conftype=0, conf=None):
temptemp.append(temp1)
self.temp_list = temptemp
+ '''
+ sensor print source select
+ '''
+ self.__sensor_print_src = __confTemp.get("sensor_print_src", None)
+
+ # temp_data_source. the following is example:
+ '''
+ "temp_data_source": [
+ {
+ "path": "/sys/s3ip/temp_sensor/",
+ "type": "temp",
+ "Unit": Unit.Temperature,
+ "read_times": 3,
+ "format": "float(float(%s)/1000)"
+ },
+ ],
+ '''
+ tmp_list = []
+ temp_data_source_conf = __confTemp.get("temp_data_source", {})
+ for item in temp_data_source_conf:
+ try:
+ path = item.get("path", None)
+ if path is None:
+ continue
+ sensor_type = item.get("type", None)
+ if sensor_type is None:
+ continue
+ number_path = "%s/%s" % (path, "number")
+ ret, number = osutil.readsysfs(number_path)
+ if ret is True:
+ for index in range(1, int(number) + 1):
+ sensor_dir = "%s%d" % (sensor_type, index)
+ # only monitored sensor add to list
+ monitor_flag_path = "%s/%s/%s" % (path, sensor_dir, "monitor_flag")
+ if os.path.exists(monitor_flag_path):
+ ret, monitor_flag = osutil.readsysfs(monitor_flag_path)
+ if ret is True and int(monitor_flag) == 0:
+ continue
+ s3ip_conf = item.copy()
+ s3ip_conf["sensor_dir"] = sensor_dir
+ obj = temp_s3ip(s3ip_conf)
+ tmp_list.append(obj)
+ except Exception:
+ pass
+ self.temp_list_s3ip = tmp_list
+
# fan
fantemp = []
fanconfig = __confTemp.get('fans', [])
@@ -105,6 +161,54 @@ def __init__(self, conftype=0, conf=None):
dcdctemp.append(dcdc1)
self.dcdc_list = dcdctemp
+ # dcdc_data_source. the following is example:
+ '''
+ "dcdc_data_source": [
+ {
+ "path": "/sys/s3ip/vol_sensor/",
+ "type": "vol",
+ "Unit": Unit.Voltage,
+ "read_times": 3,
+ "format": "float(float(%s)/1000)"
+ },
+ {
+ "path": "/sys/s3ip/curr_sensor/",
+ "type": "curr",
+ "Unit": Unit.Current,
+ "read_times": 3,
+ "format": "float(float(%s)/1000)"
+ },
+ ],
+ '''
+ dcdc_data_source_conf = __confTemp.get("dcdc_data_source", {})
+ tmp_list = []
+ for item in dcdc_data_source_conf:
+ try:
+ path = item.get("path", None)
+ if path is None:
+ continue
+ sensor_type = item.get("type", None)
+ if sensor_type is None:
+ continue
+ number_path = "%s/%s" % (path, "number")
+ ret, number = osutil.readsysfs(number_path)
+ if ret is True:
+ for index in range(1, int(number) + 1):
+ sensor_dir = "%s%d" % (sensor_type, index)
+ # only monitored sensor add to list
+ monitor_flag_path = "%s/%s/%s" % (path, sensor_dir, "monitor_flag")
+ if os.path.exists(monitor_flag_path):
+ ret, monitor_flag = osutil.readsysfs(monitor_flag_path)
+ if ret is True and int(monitor_flag) == 0:
+ continue
+ s3ip_conf = item.copy()
+ s3ip_conf["sensor_dir"] = sensor_dir
+ dcdc_obj = dcdc(s3ip_conf = s3ip_conf)
+ tmp_list.append(dcdc_obj)
+ except Exception:
+ pass
+ self.dcdc_list.extend(tmp_list)
+
# cpld
cpldtemp = []
cpldconfig = __confTemp.get('cplds', [])
@@ -316,3 +420,7 @@ def cpu(self, val):
def get_cpu_byname(self, name):
return self.cpu
+
+ @property
+ def sensor_print_src(self):
+ return self.__sensor_print_src
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
index 0f2ad2167485..e0cd231308fa 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# component.py
-# Python implementation of the Class fan
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from plat_hal.devicebase import devicebase
from plat_hal.osutil import osutil
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
index 09eed5f975ee..b0abe6e9c302 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# fan.py
-# Python implementation of the Class fan
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from plat_hal.devicebase import devicebase
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
index c6bec1abd1c2..8fb1d70e57e0 100644
--- 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
@@ -1,9 +1,20 @@
#!/usr/bin/env python3
-###############################################################################
#
-# Hardware Abstraction Layer APIs -- CPU APIs.
+# Copyright (C) 2024 Micas Networks Inc.
#
-###############################################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from plat_hal.devicebase import devicebase
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
index ba604995043d..719680f878b6 100644
--- 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
@@ -1,11 +1,30 @@
#!/usr/bin/env python3
-from plat_hal.devicebase import devicebase
-from plat_hal.sensor import sensor
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+from plat_hal.devicebase import devicebase
+from plat_hal.sensor import sensor, sensor_s3ip
class dcdc(devicebase):
- def __init__(self, conf=None):
+ def __init__(self, conf = None, s3ip_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)
+ if s3ip_conf is not None:
+ self.sensor = sensor_s3ip(s3ip_conf)
+ self.name = self.sensor.name
+ self.dcdc_id = self.sensor.sensor_id
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
index 001b4ee239bf..4d8eb6dcf511 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# devicebase.py
-# Python implementation of the Class devicebase
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import subprocess
import shlex
import ast
@@ -30,6 +40,8 @@ def get_op_value(self, node):
value = node.n
elif isinstance(node, ast.Str): # node is Str Constant
value = node.s
+ elif isinstance(node, ast.List): # node is List Constant
+ value = [element.value for element in node.elts]
else:
raise NotImplementedError("Unsupport operand type: %s" % type(node))
return value
@@ -78,7 +90,7 @@ def visit_Call(self, node):
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")
+ calc_tuple = ("float", "int", "str", "max", "min")
if node.func.id not in calc_tuple:
raise NotImplementedError("Unsupport function call type: %s" % node.func.id)
@@ -86,7 +98,10 @@ def visit_Call(self, node):
args_val_list = []
for item in node.args:
ret = self.get_op_value(item)
- args_val_list.append(ret)
+ if isinstance(ret, list):
+ args_val_list.extend(ret)
+ else:
+ args_val_list.append(ret)
if node.func.id == "str":
if len(args_val_list) != 1:
@@ -101,6 +116,16 @@ def visit_Call(self, node):
value = float(args_val_list[0])
self.value = value
return value
+
+ if node.func.id == "max":
+ value = max(args_val_list)
+ self.value = value
+ return value
+
+ if node.func.id == "min":
+ value = min(args_val_list)
+ self.value = value
+ return value
# int
if len(args_val_list) == 1:
value = int(args_val_list[0])
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
index 5b33af02527c..80543bec83a2 100644
--- 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
@@ -1,12 +1,23 @@
#!/usr/bin/env python3
-#######################################################
#
-# fan.py
-# Python implementation of the Class fan
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from eepromutil.fru import ipmifru
from eepromutil.fantlv import fan_tlv
+from eepromutil.wedge_v5 import WedgeV5
from plat_hal.devicebase import devicebase
from plat_hal.rotor import rotor
@@ -50,6 +61,7 @@ def __init__(self, conf=None):
self.EnableWatchdogConf = conf.get('EnableWatchdogConf', None)
self.led_attrs_config = conf.get('led_attrs', None)
self.led_config = conf.get('led', None)
+ self.led_map = conf.get('led_map', None)
self.Rotor_config = conf.get('Rotor', None)
self.fan_display_name_conifg = conf.get("fan_display_name", None)
rotor_tmp = []
@@ -228,6 +240,12 @@ def get_led(self):
if ret is False or value is None:
return False, 'N/A'
ledval = int(value) & mask
+ if self.led_map is not None:
+ led_color = self.led_map.get(ledval, None)
+ if led_color is None:
+ return False, 'N/A'
+ return True, led_color
+
for key, val in self.led_attrs_config.items():
if (ledval == val) and (key != "mask"):
return True, key
@@ -256,7 +274,7 @@ def get_rotor_byname(self, rotor_index):
def get_presence(self):
ret, val = self.get_value(self.present)
- if ret is False or val is None or val == "no_support":
+ if ret is False or val is None or val == "no_support" or val == "NA" or val == "ACCESS FAILED":
return False
if isinstance(val, str):
value = int(val, 16)
@@ -273,9 +291,10 @@ 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:
+ speed_pwm = rotor_item.i2c_speed
+ if speed_pwm is None:
return False
- val = round(rotor_item.i2c_speed * 100 / 255)
+ val = round(speed_pwm * 100 / 255)
return val
def feed_watchdog(self):
@@ -286,16 +305,39 @@ def feed_watchdog(self):
return ret
return ret
- def get_fru_info(self):
+ def get_wedge_v5_info(self, eeprom):
+ try:
+ product_version = None
+ product_sub_version = None
+ wegdev5 = WedgeV5()
+ rets = wegdev5.decode(eeprom)
+ for item in rets:
+ if item["code"] == wegdev5.FBWV5_PRODUCT_NAME:
+ self.productName = item["value"].replace("\x00", "").strip()
+ elif item["code"] == wegdev5.FBWV5_PRODUCT_SERIAL_NUMBER:
+ self.productSerialNumber = item["value"].replace("\x00", "").strip()
+ elif item["code"] == wegdev5.FBWV5_PRODUCT_VERSION:
+ product_version = "%d" % item["value"]
+ elif item["code"] == wegdev5.FBWV5_PRODUCT_SUB_VERSION:
+ product_sub_version = "%02d" % item["value"]
+ if product_version is not None and product_sub_version is not None:
+ self.hw_version = product_version + "." + product_sub_version
+ elif product_version is not None:
+ self.hw_version = product_version
+ elif product_sub_version is not None:
+ self.hw_version = product_sub_version
+ else:
+ self.hw_version = None
+ except Exception:
+ self.productName = None
+ self.productSerialNumber = None
+ self.hw_version = None
+ return False
+ return True
+
+ def get_fru_info(self, eeprom):
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
@@ -307,13 +349,8 @@ def get_fru_info(self):
return False
return True
- def get_tlv_info(self):
+ def get_tlv_info(self, eeprom):
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:
@@ -330,14 +367,53 @@ def get_tlv_info(self):
return False
return True
+ def decode_eeprom_by_type(self, e2_type, eeprom):
+ if e2_type == "fru":
+ return self.get_fru_info(eeprom)
+
+ if e2_type == "fantlv":
+ return self.get_tlv_info(eeprom)
+
+ if e2_type == "wedge_v5":
+ return self.get_wedge_v5_info(eeprom)
+ return False
+
+ def decode_eeprom_by_traverse(self, eeprom):
+ support_e2_type = ("fru", "fantlv", "wedge_v5")
+ for e2_type in support_e2_type:
+ status = self.decode_eeprom_by_type(e2_type, eeprom)
+ if status is True:
+ return True
+ return False
+
def decode_eeprom_info(self):
'''get fan name, hw version, sn'''
- if self.e2_type == "fru":
- return self.get_fru_info()
+ try:
+ if self.get_presence() is False:
+ raise Exception("%s: not present" % self.name)
- if self.e2_type == "fantlv":
- return self.get_tlv_info()
+ eeprom = self.get_eeprom_info(self.e2loc)
+ if eeprom is None:
+ raise Exception("%s: value is none" % self.name)
+
+ if isinstance(eeprom, bytes):
+ eeprom = self.byteTostr(eeprom)
+ if self.e2_type is None:
+ return self.decode_eeprom_by_traverse(eeprom)
+
+ if isinstance(self.e2_type, str):
+ return self.decode_eeprom_by_type(self.e2_type, eeprom)
+
+ if isinstance(self.e2_type, list):
+ for e2_type in self.e2_type:
+ status = self.decode_eeprom_by_type(e2_type, eeprom)
+ if status is True:
+ return True
+ except Exception:
+ self.productName = None
+ self.productSerialNumber = None
+ self.hw_version = None
return False
def get_AirFlow(self):
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
index 88873a029b64..e12c469e612b 100644
--- 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
@@ -1,13 +1,23 @@
#!/usr/bin/env python3
-#######################################################
#
-# interface.py
-# Python implementation of the Class interface
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import collections
from plat_hal.chassisbase import chassisbase
-from plat_hal.baseutil import baseutil
+from plat_hal.baseutil import baseutil, getplatform_name
from plat_hal.osutil import osutil
@@ -864,7 +874,7 @@ def get_dcdc_all_info(self):
tmp = dcdc.sensor.Value
if tmp is not None:
dicttmp['Value'] = tmp
- if tmp > dicttmp['Max'] or tmp < dicttmp['Min']:
+ if tmp > float(dicttmp['Max']) or tmp < float(dicttmp['Min']):
dicttmp["Status"] = "NOT OK"
else:
dicttmp["Status"] = "OK"
@@ -914,6 +924,8 @@ def get_monitor_temp_by_id(self, temp_id):
dic["High"] = self.error_ret
dic["Value"] = self.error_ret
dic["Unit"] = self.error_ret
+ dic["Invalid"] = self.error_ret
+ dic["Error"] = self.error_ret
else:
dic["Name"] = temptmp.name
dic["Api_name"] = temptmp.api_name
@@ -924,6 +936,8 @@ def get_monitor_temp_by_id(self, temp_id):
temp_value = temptmp.Value
dic["Value"] = temp_value if (temp_value is not None) else self.error_ret
dic["Unit"] = temptmp.Unit
+ dic["Invalid"] = temptmp.temp_invalid
+ dic["Error"] = temptmp.temp_error
return dic
def get_temp_info(self):
@@ -942,6 +956,22 @@ def get_temp_info(self):
val_list[temp.name] = dic
return val_list
+ def get_temp_info_s3ip(self):
+ val_list = collections.OrderedDict()
+ # temp
+ templist = self.chas.temp_list_s3ip
+ 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
@@ -1337,3 +1367,10 @@ def get_cpu_reboot_cause(self):
return "Unknown reboot cause"
return cpu.get_cpu_reboot_cause()
+ def get_sensor_print_src(self):
+ """
+ Get sensor data source
+ @return string of sensor data source
+ """
+ return self.chas.sensor_print_src
+
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
index 7fb869c74d7f..0ae751b81e3d 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# led.py
-# Python implementation of the Class led
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from plat_hal.devicebase import devicebase
@@ -15,6 +25,7 @@ def __init__(self, conf=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)
+ self.led_map = conf.get('led_map', None)
def set_color(self, color):
status = self.led_attrs_config.get(color, None)
@@ -46,6 +57,11 @@ def get_color(self):
if ret is False or value is None:
return False, 'N/A'
ledval = int(value) & mask
+ if self.led_map is not None:
+ led_color = self.led_map.get(ledval, None)
+ if led_color is None:
+ return False, 'N/A'
+ return True, led_color
for key, val in self.led_attrs_config.items():
if (ledval == val) and (key != "mask"):
return True, key
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
index 9ac32cace263..d09fa70973c7 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# onie_e2.py
-# Python implementation of the Class onie_e2
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from plat_hal.devicebase import devicebase
from eepromutil.onietlv import onie_tlv
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
index 684e26bb9ecd..4501bcf5f29a 100644
--- 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
@@ -1,10 +1,19 @@
#!/usr/bin/env python3
-#######################################################
#
-# osutil.py
-# Python implementation of the Class osutil
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
import os
import glob
@@ -53,37 +62,31 @@ def wrapper(*args, **kwargs):
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
+ platform_hal_debug("%s file_rw_lock success, pidfile: %s" % (file_path, pidfile))
+ return True, pidfile
except Exception:
if pidfile is not None:
pidfile.close()
pidfile = None
- return False
+ return False, pidfile
-def file_rw_unlock():
+def file_rw_unlock(pidfile):
try:
- global pidfile
-
if pidfile is not None:
fcntl.flock(pidfile, fcntl.LOCK_UN)
pidfile.close()
+ platform_hal_debug("file_rw_unlock success, pidfile: %s" % pidfile)
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)))
+ platform_hal_debug("file_rw_unlock err, pidfile: %s, msg: %s" % (pidfile, str(e)))
return False
@@ -91,11 +94,11 @@ def take_file_rw_lock(file_path):
loop = 1000
ret = False
for i in range(0, loop):
- ret = file_rw_lock(file_path)
+ ret, pidfile = file_rw_lock(file_path)
if ret is True:
break
time.sleep(0.001)
- return ret
+ return ret, pidfile
class osutil(object):
@@ -252,6 +255,7 @@ def io_rd(reg_addr, read_len=1):
@staticmethod
def readsysfs(location, flock_path=None):
flock_path_tmp = None
+ pidfile = None
platform_hal_debug("readsysfs, location:%s, flock_path:%s" % (location, flock_path))
try:
if flock_path is not None:
@@ -259,7 +263,7 @@ def readsysfs(location, flock_path=None):
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)
+ ret, pidfile = 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)
@@ -270,14 +274,14 @@ def readsysfs(location, flock_path=None):
with open(locations[0], 'rb') as fd1:
retval = fd1.read()
retval = osutil.byteTostr(retval)
- if flock_path_tmp is not None:
- file_rw_unlock()
+ if pidfile is not None:
+ file_rw_unlock(pidfile)
retval = retval.rstrip('\r\n')
retval = retval.lstrip(" ")
except Exception as e:
- if flock_path_tmp is not None:
- file_rw_unlock()
+ if pidfile is not None:
+ file_rw_unlock(pidfile)
platform_hal_debug("readsysfs error, msg:%s" % str(e))
return False, (str(e) + " location[%s]" % location)
return True, retval
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
index a7fc90e0fe23..c62da1929d34 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# psu.py
-# Python implementation of the Class psu
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from eepromutil.fru import ipmifru
from eepromutil.cust_fru import CustFru
from plat_hal.devicebase import devicebase
@@ -428,7 +438,7 @@ def psu_not_present_pwm(self, val):
@property
def present(self):
ret, val = self.get_value(self.__presentconfig)
- if ret is False or val is None or val == "no_support":
+ if ret is False or val is None or val == "no_support" or val == "NA" or val == "ACCESS FAILED":
return False
mask = self.__presentconfig.get("mask")
if isinstance(val, str):
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
index ff120cb474b2..0b96bf340ce3 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# rotor.py
-# Python implementation of the Class rotor
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
from plat_hal.devicebase import devicebase
from plat_hal.sensor import sensor
@@ -32,7 +42,7 @@ def __init__(self, conf=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":
+ if ret is False or val is None or val == "no_support" or val == "NA" or val == "ACCESS FAILED":
return False
if isinstance(val, str):
value = int(val, 16)
@@ -120,7 +130,7 @@ 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:
+ if ret is False or val is None or val == "no_support" or val == "NA" or val == "ACCESS FAILED":
return False
if isinstance(val, str):
value = int(val, 16)
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
index af2a5384b618..99396923c41a 100644
--- 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
@@ -1,10 +1,20 @@
#!/usr/bin/env python3
-#######################################################
#
-# sensor.py
-# Python implementation of the Class sensor
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import time
from plat_hal.devicebase import devicebase
@@ -103,9 +113,9 @@ 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:
+ if i != (read_times - 1):
+ time.sleep(0.01)
continue
val_list.append(real_value)
val_list.sort()
@@ -272,3 +282,65 @@ def __str__(self):
self.Max, self.Unit,
self.format)
return tmpstr
+
+class sensor_s3ip(sensor):
+ def __init__(self, s3ip_conf):
+ self.s3ip_conf = s3ip_conf
+ value_conf = {}
+ value_conf["loc"] = "%s/%s/%s" % (self.s3ip_conf.get("path"), self.s3ip_conf.get("sensor_dir"), "value")
+ value_conf["way"] = "sysfs"
+ conf = {}
+ conf["value"] = value_conf
+ conf["read_times"] = s3ip_conf.get("read_times", 1)
+ conf["Unit"] = unit = s3ip_conf.get("Unit", None)
+ conf["format"] = unit = s3ip_conf.get("format", None)
+ super(sensor_s3ip, self).__init__(conf)
+ self.min_path = "%s/%s/%s" % (self.s3ip_conf.get("path"), self.s3ip_conf.get("sensor_dir"), "min")
+ self.max_path = "%s/%s/%s" % (self.s3ip_conf.get("path"), self.s3ip_conf.get("sensor_dir"), "max")
+ self.alias = "%s/%s/%s" % (self.s3ip_conf.get("path"), self.s3ip_conf.get("sensor_dir"), "alias")
+ self.sensor_id = self.s3ip_conf.get("type").upper()
+
+ @property
+ def Min(self):
+ try:
+ ret, val = self.get_sysfs(self.min_path)
+ if ret is True:
+ return val
+ except Exception:
+ pass
+ return None
+
+ @Min.setter
+ def Min(self, val):
+ try:
+ return self.set_sysfs(self.min_path, val)
+ except Exception as e:
+ return False, (str(e) + " location[%s][%d]" % (self.min_path, val))
+
+ @property
+ def Max(self):
+ try:
+ ret, val = self.get_sysfs(self.max_path)
+ if ret is True:
+ return val
+ except Exception:
+ pass
+ return None
+
+ @Max.setter
+ def Max(self, val):
+ try:
+ return self.set_sysfs(self.max_path, val)
+ except Exception as e:
+ return False, (str(e) + " location[%s][%d]" % (self.max_path, val))
+
+ @property
+ def name(self):
+ try:
+ ret, val = self.get_sysfs(self.alias)
+ if ret is True:
+ return val
+ except Exception:
+ pass
+ return None
+
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
index a202c20339c9..1dbd443f71c3 100644
--- 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
@@ -1,14 +1,23 @@
#!/usr/bin/env python3
-#######################################################
#
-# temp.py
-# Python implementation of the Class temp
+# Copyright (C) 2024 Micas Networks Inc.
#
-#######################################################
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import os
import syslog
-from plat_hal.sensor import sensor
-
+from plat_hal.sensor import sensor, sensor_s3ip
PLATFORM_HAL_TEMP_DEBUG_FILE = "/etc/.platform_hal_temp_debug_flag"
@@ -82,7 +91,7 @@ def get_max_value(self, conf):
ret, val = self.get_value(conf)
if ret is False or val is None:
return None
- return val
+ return float(val)
except Exception:
return None
@@ -120,6 +129,25 @@ def Value(self):
self.__Value = int(max_val)
else:
self.__Value = self.get_format_value(self.format % max_val)
+ elif isinstance(self.ValueConfig, dict) and self.ValueConfig.get("val_conf_list") is not None:
+ val_list = []
+ fail_set = set()
+ for index, val_conf_item in enumerate(self.ValueConfig["val_conf_list"]):
+ val_tmp = self.get_max_value(val_conf_item)
+ if val_tmp is None:
+ fail_set.add(index)
+ fail_val = val_conf_item.get("fail_val")
+ if fail_val is None:
+ return None
+ val_tmp = fail_val
+ val_list.append(val_tmp)
+ # check fail set
+ fail_conf_set_list = self.ValueConfig.get("fail_conf_set_list",[])
+ for item in fail_conf_set_list:
+ if item.issubset(fail_set):
+ return None
+ val_tuple = tuple(val_list)
+ self.__Value = self.get_format_value(self.ValueConfig["format"] % (val_tuple))
else:
ret, val = self.get_value(self.ValueConfig)
if ret is False or val is None:
@@ -137,3 +165,8 @@ def Value(self):
@Value.setter
def Value(self, val):
self.__Value = val
+
+class temp_s3ip(sensor_s3ip):
+ def __init__(self, s3ip_conf = None):
+ super(temp_s3ip, self).__init__(s3ip_conf)
+ self.temp_id = s3ip_conf.get("type").upper()
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
index 2cb7f5273a44..86e102594cab 100755
--- 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
@@ -1,11 +1,26 @@
#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
import os
import syslog
import requests
+
class RestfulApiClient():
Debug_file = "/tmp/restful_api_debug"
BmcBaseUrl = 'http://240.1.1.2:8080'
@@ -14,12 +29,13 @@ class RestfulApiClient():
HostnameUrl = '/api/v1.0/hostname'
EventsUrl = '/api/v1.0/events'
SensorsUrl = '/api/v1.0/sys_switch/sensors'
+ TempSensorsUrl = '/api/v1.0/sys_switch/temp_sensor'
+ VolSensorsUrl = '/api/v1.0/sys_switch/vol_sensor'
+ CurSensorsUrl = '/api/v1.0/sys_switch/cur_sensor'
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'
@@ -28,7 +44,6 @@ class RestfulApiClient():
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")
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
index 340a1f7a733f..fdc4410e2c20 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/baseutil.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/baseutil.py
@@ -1,4 +1,20 @@
#!/usr/bin/env python3
+#
+# Copyright (C) 2024 Micas Networks Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
import os
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
index 5f1659b3bbf0..d474cffa2d35 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/smbus.py
+++ b/platform/broadcom/sonic-platform-modules-micas/common/lib/wbutil/smbus.py
@@ -1,25 +1,19 @@
#!/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:
+# Copyright (C) 2024 Micas Networks Inc.
#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
+# 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.
#
-# 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.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
import os
import sys
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/modules/Makefile
index e432430dba46..4e106f013819 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/Makefile
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/Makefile
@@ -8,9 +8,11 @@ module_out_put_dir := $(PWD)/build
export module_out_put_dir
PLAT_SYSFS_DIR = $(PWD)/plat_sysfs
+S3IP_SYSFS_DIR = $(PWD)/s3ip_sysfs
PINCTRL = $(PWD)/pinctrl
export PLAT_SYSFS_DIR
+export S3IP_SYSFS_DIR
platform_common-objs := platform_common_module.o dfd_tlveeprom.o
obj-m += platform_common.o
@@ -39,9 +41,14 @@ obj-m += wb_i2c_mux_pca9641.o
obj-m += wb_i2c_mux_pca954x.o
obj-m += wb_xdpe132g5c_pmbus.o
obj-m += wb_i2c_gpio_device.o
+obj-m += ct7148.o
+obj-m += wb_ucd9081.o
+obj-m += wb_indirect_dev.o
+
all :
$(MAKE) -C $(PLAT_SYSFS_DIR)
+ $(MAKE) -C $(S3IP_SYSFS_DIR)
$(MAKE) -C $(PINCTRL)
$(MAKE) -C $(KERNEL_SRC)/build M=$(PWD) modules
@if [ ! -d $(module_out_put_dir) ]; then mkdir -p $(module_out_put_dir) ;fi
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/ct7148.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/ct7148.c
new file mode 100644
index 000000000000..fff4b0e0eecc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/ct7148.c
@@ -0,0 +1,237 @@
+/*
+ * An ct7148 driver for tmp ct7148 function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* debug switch level */
+typedef enum {
+ DBG_START,
+ DBG_VERBOSE,
+ DBG_KEY,
+ DBG_WARN,
+ DBG_ERROR,
+ DBG_END,
+} dbg_level_t;
+
+static int debuglevel = 0;
+module_param(debuglevel, int, S_IRUGO | S_IWUSR);
+
+#define CT7318_DEBUG(fmt, arg...) do { \
+ if (debuglevel > DBG_START && debuglevel < DBG_ERROR) { \
+ printk(KERN_INFO "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \
+ } else if (debuglevel >= DBG_ERROR) { \
+ printk(KERN_ERR "[DEBUG]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \
+ } else { } \
+} while (0)
+
+#define CT7318_ERROR(fmt, arg...) do { \
+ if (debuglevel > DBG_START) { \
+ printk(KERN_ERR "[ERROR]:<%s, %d>:"fmt, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } while (0)
+
+enum chips { ct7318 };
+
+/* The CT7318 registers */
+#define CT7318_CONFIG_REG_1 0x09
+#define CT7318_CONVERSION_RATE_REG 0x0A
+#define CT7318_MANUFACTURER_ID_REG 0xFE
+#define CT7318_DEVICE_ID_REG 0xFF
+
+static const u8 CT7318_TEMP_MSB[2] = { 0x00, 0x01 };
+static const u8 CT7318_TEMP_LSB[2] = { 0x15, 0x10 };
+
+/* Flags */
+#define CT7318_CONFIG_SHUTDOWN 0x40
+#define CT7318_CONFIG_RANGE 0x04
+
+/* Manufacturer / Device ID's */
+#define CT7318_MANUFACTURER_ID 0x59
+#define CT7318_DEVICE_ID 0x8D
+
+static const struct i2c_device_id ct7318_id[] = {
+ { "ct7318", 2 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ct7318_id);
+
+static const struct of_device_id ct7318_of_match[] = {
+ {.compatible = "sensylink,ct7318"},
+ { },
+};
+MODULE_DEVICE_TABLE(of, ct7318_of_match);
+
+struct ct7318_data {
+ struct i2c_client *client;
+ struct mutex update_lock;
+ u32 temp_config[5];
+ struct hwmon_channel_info temp_info;
+ const struct hwmon_channel_info *info[2];
+ struct hwmon_chip_info chip;
+ char valid;
+ unsigned long last_updated;
+ unsigned long channels;
+ u8 config;
+ s16 temp[4];
+};
+
+static int ct7318_register_to_temp(s16 reg)
+{
+ s16 tmp_val;
+ int val;
+
+ CT7318_DEBUG("reg_data, data=0x%04x \n", reg);
+
+ /* Positive number:reg*0.125 */
+ if (!(reg & 0x400)) {
+ val = reg * 125;
+ /* Negative number: The first bit is the sign bit, and the rest is inverted +1 */
+ } else {
+ tmp_val = ((~((s16)reg)) & 0x7ff) + 1;
+ CT7318_DEBUG("ct7318, tmp_val=0x%08x -- %d\n", tmp_val, tmp_val);
+ val = -(tmp_val * 125);
+ }
+
+ CT7318_DEBUG("ct7318 reg2data, val=0x%08x -- %d \n", val, val);
+
+ return val;
+}
+
+static struct ct7318_data *ct7318_update_device(struct device *dev)
+{
+ struct ct7318_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int i;
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + (HZ / 16)) || !data->valid) {
+
+ for (i = 0; i < data->channels; i++) {
+ data->temp[i] = i2c_smbus_read_byte_data(client, CT7318_TEMP_MSB[i]) << 3;
+ data->temp[i] |= (i2c_smbus_read_byte_data(client, CT7318_TEMP_LSB[i]) >> 5);
+ }
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+static int ct7318_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct ct7318_data *ct7318 = ct7318_update_device(dev);
+
+ switch (attr) {
+ case hwmon_temp_input:
+ *val = ct7318_register_to_temp(ct7318->temp[channel]);
+ return 0;
+ case hwmon_temp_fault:
+ /*
+ * The OPEN bit signals a fault. This is bit 0 of the temperature
+ * register (low byte).
+ */
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t ct7318_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel)
+{
+ switch (attr) {
+ case hwmon_temp_fault:
+ if (channel == 0) {
+ return 0;
+ }
+ return 0444;
+ case hwmon_temp_input:
+ return 0444;
+ default:
+ return 0;
+ }
+}
+
+static const struct hwmon_ops ct7318_ops = {
+ .read = ct7318_read,
+ .is_visible = ct7318_is_visible,
+};
+
+static int ct7318_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct device *hwmon_dev;
+ struct ct7318_data *data;
+ int i;
+
+ data = devm_kzalloc(dev, sizeof(struct ct7318_data), GFP_KERNEL);
+ if (!data) {
+ return -ENOMEM;
+ }
+
+ mutex_init(&data->update_lock);
+
+ data->channels = i2c_match_id(ct7318_id, client)->driver_data;
+ data->client = client;
+
+ for (i = 0; i < data->channels; i++) {
+ data->temp_config[i] = HWMON_T_INPUT;
+ }
+
+ data->chip.ops = &ct7318_ops;
+ data->chip.info = data->info;
+
+ data->info[0] = &data->temp_info;
+
+ data->temp_info.type = hwmon_temp;
+ data->temp_info.config = data->temp_config;
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, &data->chip, NULL);
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static struct i2c_driver ct7318_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "ct7318",
+ .of_match_table = of_match_ptr(ct7318_of_match),
+ },
+ .probe_new = ct7318_probe,
+ .id_table = ct7318_id,
+};
+
+module_i2c_driver(ct7318_driver);
+
+MODULE_AUTHOR("sonic_rd@whitebox");
+MODULE_DESCRIPTION("Sensylink CT7318 temperature sensor driver");
+MODULE_LICENSE("GPL");
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
index 0d6f38ecc551..7469c760a568 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.c
@@ -1,9 +1,11 @@
/*
- * Copyright (C) 2003-2014 FreeIPMI Core Team
+ * An dfd_tlveeprom driver for dfd rlveeprom function
*
- * This program is free software: you can redistribute it and/or modify
+ * Copyright (C) 2024 Micas Networks Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
+ * 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,
@@ -12,33 +14,10 @@
* 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 .
- *
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/*****************************************************************************\
- * 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
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
index 6eaac5848223..30991eca5bc8 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/dfd_tlveeprom.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_tlveeprom driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef DFD_OPENBMC_TLVEEPROM_H
#define 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
index 649a8452debe..293484605cf7 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/fpga_i2c.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/fpga_i2c.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for fpga_i2c driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _FPGA_I2C_H
#define _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
index e74f4e800582..84d3f54943fd 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.c
@@ -1,9 +1,21 @@
/*
- * hw_test.c
- * Original Author : support, 2020-10-15
+ * An hw_test driver for hw test read/write function
*
- * History
- * v1.0 support 2020-10-15 Initial version.
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
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
index 695fa336c4ff..231396390272 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/hw_test.h
@@ -1,3 +1,22 @@
+/*
+ * A header definition for hw_test driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef _LINUX_DRAM_DRIVER_H
#define _LINUX_DRAM_DRIVER_H
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/core.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/core.h
index 840103c40c14..81655ead6007 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/core.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/core.h
@@ -1,11 +1,24 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Core private header for the pin control subsystem
+ * A header definition for pin control subsystem
*
+ * Copyright (C) 2024 Micas Networks Inc.
+ *
+ * Based on core.h
* Copyright (C) 2011 ST-Ericsson SA
- * Written on behalf of Linaro for ST-Ericsson
*
- * Author: Linus Walleij
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000.c
index 753c8a061a86..7689ba1371bf 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000.c
@@ -1,9 +1,21 @@
-// SPDX-License-Identifier: GPL-2.0
/*
- * Intel Denverton SoC pinctrl/GPIO driver
+ * An wb_gpio_c3000 driver for gpio c3000 function
*
- * Copyright (C) 2017, Intel Corporation
- * Author: Mika Westerberg
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000_device.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000_device.c
index 33ab19a5ac44..ddfc5791b706 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000_device.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_gpio_c3000_device.c
@@ -1,3 +1,23 @@
+/*
+ * An wb_gpio_c3000_device driver for gpio c3000 device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.c
index 7a52f17ac8f9..98d735ea6a1a 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.c
@@ -1,10 +1,24 @@
-// SPDX-License-Identifier: GPL-2.0
/*
- * Intel pinctrl/GPIO core driver.
+ * An wb_pinctrl_intel driver for pinctrl intel function
*
+ * Copyright (C) 2024 Micas Networks Inc.
+ *
+ * Based on pinctrl-intel.c
* Copyright (C) 2015, Intel Corporation
- * Authors: Mathias Nyman
- * Mika Westerberg
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.h
index 5ed0cc0651a5..111edabacfcc 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/pinctrl/wb_pinctrl_intel.h
@@ -1,10 +1,24 @@
-/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Core pinctrl/GPIO driver for Intel GPIO controllers
+ * A header definition for pinctrl_intel driver
*
+ * Copyright (C) 2024 Micas Networks Inc.
+ *
+ * Based on pinctrl-intel.h
* Copyright (C) 2015, Intel Corporation
- * Authors: Mathias Nyman
- * Mika Westerberg
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PINCTRL_INTEL_H
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg.c
index 22962556eb0d..44bfe8e95b6f 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_cfg driver for cfg function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_adapter.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_adapter.c
index 9c8dc6aa098e..cd26851725cc 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_adapter.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_adapter.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_cfg_adapter driver for cfg adapter function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_file.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_file.c
index ac1c22ff1c51..eaf58f6bc519 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_file.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_file.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_cfg_file driver for cfg file function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_info.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_info.c
index c1ad958bc8bb..26a7fab2c967 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_info.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_info.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_cfg_info driver for cfg information function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
@@ -551,6 +571,22 @@ static int dfd_info_reg2data_mac_th5(int data, int *temp_value)
return DFD_RV_OK;
}
+static int dfd_info_reg2data_mac_th4(int data, int *temp_value)
+{
+ int tmp_val;
+ int val;
+
+ DBG_DEBUG(DBG_VERBOSE, "reg2data_mac_th4, data=%d\n", data);
+
+ tmp_val = data >> 4;
+ val = 356070 - (((tmp_val - 2) * 237340) / 2000);
+
+ DBG_DEBUG(DBG_VERBOSE, "reg2data_mac_th4, val=%d\n", val);
+ *temp_value = val;
+
+ return DFD_RV_OK;
+}
+
static int dfd_info_reg2data_mac_td3(int data, int *temp_value)
{
int val;
@@ -658,6 +694,9 @@ static int dfd_info_get_cpld_temperature(int key, int *value)
case MAC_TD3:
rv = dfd_info_reg2data_mac_td3(temp_reg, &temp_value);
break;
+ case MAC_TH4:
+ rv = dfd_info_reg2data_mac_th4(temp_reg, &temp_value);
+ break;
default:
temp_value = temp_reg;
rv = DFD_RV_OK;
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_listnode.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_listnode.c
index d6fd7e104c9f..450d8a360173 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_listnode.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/cfg/dfd_cfg_listnode.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_cfg_listnode driver for cfg listnode function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_fan_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_fan_driver.c
index d8965d75c9c0..203a8cc0d637 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_fan_driver.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_fan_driver.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_fan_driver driver for dfd fan function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_module.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_module.c
index 9e5b00b795de..c937cb790fd1 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_module.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_module.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_module driver for dfd module function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include "../dev_sysfs/include/sysfs_common.h"
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_psu_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_psu_driver.c
index 55e2e4339ae7..bb0eba0bfa05 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_psu_driver.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_psu_driver.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_psu_driver driver for dfd psu function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sensors_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sensors_driver.c
index bfca20290efb..433a51dc75ff 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sensors_driver.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sensors_driver.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_sensor_driver driver for dfd sensor function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sff_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sff_driver.c
index 5c1faff975b1..f768c5640e76 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sff_driver.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_sff_driver.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_sff_driver driver for dfd sff function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include "./include/dfd_module.h"
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_slot_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_slot_driver.c
index 69c82adabef0..6e3c70abea6f 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_slot_driver.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/dfd_slot_driver.c
@@ -1,3 +1,23 @@
+/*
+ * An dfd_slot_driver driver for dfd slot function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg.h
index af3de1ca9938..2b698f37af61 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_cfg driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __DFD_CFG_H__
#define __DFD_CFG_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_adapter.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_adapter.h
index 70d8b536c437..c599250dd225 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_adapter.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_adapter.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_cfg_adapter driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __DFD_CFG_ADAPTER_H__
#define __DFD_CFG_ADAPTER_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_file.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_file.h
index 50d7a42d5564..d74bfae0d697 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_file.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_file.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_cfg_file driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __DFD_CFG_FILE_H__
#define __DFD_CFG_FILE_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_info.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_info.h
index 88e8f92c10fe..def93cd51353 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_info.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_info.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_cfg_info driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __DFD_CFG_INFO_H__
#define __DFD_CFG_INFO_H__
@@ -97,7 +117,8 @@ typedef enum sensor_format_mem_s {
LINEAR16,
TMP464,
MAC_TH5,
- MAC_TD3
+ MAC_TD3,
+ MAC_TH4
} sensor_format_mem_t;
typedef int (*info_hwmon_buf_f)(uint8_t *buf, int buf_len, uint8_t *buf_new, int *buf_len_new, info_ctrl_t *info_ctrl);
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_listnode.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_listnode.h
index 955dfa96e42e..9c4bb057beb8 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_listnode.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_cfg_listnode.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_cfg_listnode driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __DFD_CFG_LISTNODE_H__
#define __DFD_CFG_LISTNODE_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_fan_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_fan_driver.h
index 1065fd9eed3f..e1987b0f06cd 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_fan_driver.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_fan_driver.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_fan_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _DFD_FAN_DRIVER_H_
#define _DFD_FAN_DRIVER_H_
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_module.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_module.h
index a547255cf3ab..8ed110e7ae69 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_module.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_module.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_module driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __DFD_MODULE_H__
#define __DFD_MODULE_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_psu_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_psu_driver.h
index ce7199660557..a9d7f465915e 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_psu_driver.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_psu_driver.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_psu_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _DFD_PSU_DRIVER_H_
#define _DFD_PSU_DRIVER_H_
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sensors_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sensors_driver.h
index 16733b26029f..25998164ab36 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sensors_driver.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sensors_driver.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_sensor_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _DFD_SENSORS_DRIVER_H_
#define _DFD_SENSORS_DRIVER_H_
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sff_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sff_driver.h
index 7107b72ee4b2..3e9305d6647c 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sff_driver.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_sff_driver.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_aff_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _DFD_SFF_DRIVER_H_
#define _DFD_SFF_DRIVER_H_
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_slot_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_slot_driver.h
index c68caecd2e66..1e628c0e9754 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_slot_driver.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_cfg/include/dfd_slot_driver.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for dfd_slot_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _DFD_SLOT_DRIVER_H_
#define _DFD_SLOT_DRIVER_H_
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/plat_switch.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/plat_switch.h
index bbd813e87114..b862ef7121cf 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/plat_switch.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/plat_switch.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for plat_switch driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _PLAT_SWITCH_H_
#define _PLAT_SWITCH_H_
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/sysfs_common.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/sysfs_common.h
index 5b73731e1fbf..4ac0cee1a4a6 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/sysfs_common.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/include/sysfs_common.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for sysfs_common driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _SYSFS_COMMON_H_
#define _SYSFS_COMMON_H_
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_fan.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_fan.c
index 931c7c243a21..3809da9ec1a1 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_fan.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_fan.c
@@ -1,8 +1,21 @@
/*
- * plat_fan.c
+ * An plat_fan driver for plat fan function
*
- * This module create fan kobjects and attributes in /sys/wb_plat/fan
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_psu.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_psu.c
index 197f94b64991..4207b9bc8ca7 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_psu.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_psu.c
@@ -1,8 +1,21 @@
/*
- * plat_psu.c
+ * An plat_psu driver for plat psu function
*
- * This module create psu kobjects and attributes in /sys/wb_plat/psu
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sensor.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sensor.c
index aaf62f4c1a3c..da7d5a872350 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sensor.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sensor.c
@@ -1,7 +1,21 @@
/*
- * plat_sensor.c
+ * An plat_sensor driver for plat sensor function
*
- * This module create sensor kobjects and attributes in /sys/wb_plat/sensor
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sff.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sff.c
index 50c0f78aede9..cf2cd5181f01 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sff.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_sff.c
@@ -1,8 +1,21 @@
/*
- * plat_sff.c
+ * An plat_sff driver for plat sff function
*
- * This module create sff kobjects and attributes in /sys/wb_plat/sff
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_slot.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_slot.c
index 7c50f283bd06..979de7418475 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_slot.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_slot.c
@@ -1,8 +1,21 @@
/*
- * plat_slot.c
+ * An plat_slot driver for plat slot function
*
- * This module create sff kobjects and attributes in /sys/wb_plat/slot
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_switch.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_switch.c
index fea008b41bfe..e36ff6657c90 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_switch.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/plat_sysfs/dev_sysfs/plat_switch.c
@@ -1,11 +1,23 @@
/*
- * plat_switch.c
+ * An plat_switch driver for plat switch function
*
- * This module create a kset in sysfs called /sys/wb_plat
- * Then other switch kobjects are created and assigned to this kset,
- * such as "board", "cpld", "fan", "psu", "sff", ...
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include "./include/plat_switch.h"
#define SWITCH_INFO(fmt, args...) LOG_INFO("switch: ", fmt, ##args)
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common.h
index 9e4a4fae00c1..ffd752204e4f 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for platfrom_common driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __PLATFORM_COMMON_H__
#define __PLATFORM_COMMON_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common_module.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common_module.c
index 189a3aa056b2..57f436e5b8af 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common_module.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/platform_common_module.c
@@ -1,3 +1,23 @@
+/*
+ * An platform_common_module driver for platform common modules function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/pmbus.h
index 10fb17879f8e..853dba4333e3 100755
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/pmbus.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/pmbus.h
@@ -1,9 +1,25 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * pmbus.h - Common defines and structures for PMBus devices
+ * A header definition for pmbus driver
*
+ * Copyright (C) 2024 Micas Networks Inc.
+ *
+ * Based on kernel pmbus.h
* Copyright (c) 2010, 2011 Ericsson AB.
* Copyright (c) 2012 Guenter Roeck
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PMBUS_H
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/Makefile
new file mode 100644
index 000000000000..c4e5d6928bb0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/Makefile
@@ -0,0 +1,19 @@
+PWD = $(shell pwd)
+SYSFS_OUT_PUT := $(PWD)/build
+sysfs_out_put_dir := $(SYSFS_OUT_PUT)/S3IP_sysfs/
+sysfs_cfg_dir := $(SYSFS_OUT_PUT)/dfd_cfg/
+export sysfs_out_put_dir sysfs_cfg_dir
+
+SYSFS_DRIVER_DIR = $(PWD)/sysfs_driver
+SWITCH_DRIVER_DIR = $(PWD)/switch_driver
+DEVICE_DRIVER_DIR = $(PWD)/device_driver
+
+export SYSFS_DRIVER_DIR SWITCH_DRIVER_DIR
+
+all :
+ $(MAKE) -C $(SYSFS_DRIVER_DIR)
+ $(MAKE) -C $(SWITCH_DRIVER_DIR)
+ $(MAKE) -C $(DEVICE_DRIVER_DIR)
+
+clean :
+ -rm -rf $(SYSFS_OUT_PUT)
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/Makefile
new file mode 100644
index 000000000000..a971e0bf3844
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/Makefile
@@ -0,0 +1,36 @@
+PWD = $(shell pwd)
+
+MAKEFILE_FILE_PATH = $(abspath $(lastword $(MAKEFILE_LIST)))
+DEV_SYSFS_HEADER_DIR = $(abspath $(MAKEFILE_FILE_PATH)/../../sysfs_driver/include)
+SWITCH_DVR_HEADER_DIR = $(abspath $(MAKEFILE_FILE_PATH)/../../switch_driver/include)
+EXTRA_CFLAGS:= -I$(M)/include
+EXTRA_CFLAGS+= -I$(DEV_SYSFS_HEADER_DIR)
+EXTRA_CFLAGS+= -I$(SWITCH_DVR_HEADER_DIR)
+EXTRA_CFLAGS+= -Wall
+
+KBUILD_EXTRA_SYMBOLS += $(SYSFS_DRIVER_DIR)/Module.symvers
+KBUILD_EXTRA_SYMBOLS += $(SWITCH_DRIVER_DIR)/Module.symvers
+
+obj-m := syseeprom_device_driver.o
+obj-m += fan_device_driver.o
+obj-m += cpld_device_driver.o
+obj-m += sysled_device_driver.o
+obj-m += slot_device_driver.o
+obj-m += psu_device_driver.o
+obj-m += transceiver_device_driver.o
+obj-m += temp_sensor_device_driver.o
+obj-m += vol_sensor_device_driver.o
+obj-m += curr_sensor_device_driver.o
+obj-m += fpga_device_driver.o
+obj-m += watchdog_device_driver.o
+obj-m += system_device_driver.o
+obj-m += eeprom_device_driver.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
+ rm -f $(PWD)/Module.markers $(PWD)/Module.symvers $(PWD)/modules.order
+ rm -rf $(PWD)/.tmp_versions
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/cpld_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/cpld_device_driver.c
new file mode 100644
index 000000000000..de760b7bc775
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/cpld_device_driver.c
@@ -0,0 +1,217 @@
+/*
+ * An cpld_device_driver driver for cpld devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "device_driver_common.h"
+#include "cpld_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define CPLD_INFO(fmt, args...) LOG_INFO("cpld: ", fmt, ##args)
+#define CPLD_ERR(fmt, args...) LOG_ERR("cpld: ", fmt, ##args)
+#define CPLD_DBG(fmt, args...) LOG_DBG("cpld: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/******************************************CPLD***********************************************/
+static int wb_get_main_board_cpld_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_cpld_number);
+
+ ret = g_drv->get_main_board_cpld_number();
+ return ret;
+}
+
+/*
+ * wb_get_main_board_cpld_alias - Used to identify the location of cpld,
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_cpld_alias(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_cpld_alias);
+
+ ret = g_drv->get_main_board_cpld_alias(cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_cpld_type - Used to get cpld model name
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_cpld_type(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_cpld_type);
+
+ ret = g_drv->get_main_board_cpld_type(cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_cpld_firmware_version - Used to get cpld firmware version,
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_cpld_firmware_version(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_cpld_firmware_version);
+
+ ret = g_drv->get_main_board_cpld_firmware_version(cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_cpld_board_version - Used to get cpld board version,
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_cpld_board_version(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_cpld_board_version);
+
+ ret = g_drv->get_main_board_cpld_board_version(cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_cpld_test_reg - Used to test cpld register read
+ * filled the value to buf, value is hexadecimal, start with 0x
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_cpld_test_reg(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_cpld_test_reg);
+
+ ret = g_drv->get_main_board_cpld_test_reg(cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_main_board_cpld_test_reg - Used to test cpld register write
+ * @cpld_index: start with 1
+ * @value: value write to cpld
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_main_board_cpld_test_reg(unsigned int cpld_index, unsigned int value)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_main_board_cpld_test_reg);
+
+ ret = g_drv->set_main_board_cpld_test_reg(cpld_index, value);
+ return ret;
+}
+/***************************************end of CPLD*******************************************/
+
+static struct s3ip_sysfs_cpld_drivers_s drivers = {
+ /*
+ * set ODM CPLD drivers to /sys/s3ip/cpld,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_main_board_cpld_number = wb_get_main_board_cpld_number,
+ .get_main_board_cpld_alias = wb_get_main_board_cpld_alias,
+ .get_main_board_cpld_type = wb_get_main_board_cpld_type,
+ .get_main_board_cpld_firmware_version = wb_get_main_board_cpld_firmware_version,
+ .get_main_board_cpld_board_version = wb_get_main_board_cpld_board_version,
+ .get_main_board_cpld_test_reg = wb_get_main_board_cpld_test_reg,
+ .set_main_board_cpld_test_reg = wb_set_main_board_cpld_test_reg,
+};
+
+static int __init cpld_device_driver_init(void)
+{
+ int ret;
+
+ CPLD_INFO("cpld_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_cpld_drivers_register(&drivers);
+ if (ret < 0) {
+ CPLD_ERR("cpld drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+
+ CPLD_INFO("cpld_init success.\n");
+ return 0;
+}
+
+static void __exit cpld_device_driver_exit(void)
+{
+ s3ip_sysfs_cpld_drivers_unregister();
+ CPLD_INFO("cpld_exit success.\n");
+ return;
+}
+
+module_init(cpld_device_driver_init);
+module_exit(cpld_device_driver_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("cpld device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/curr_sensor_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/curr_sensor_device_driver.c
new file mode 100644
index 000000000000..1c2a1e25f6de
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/curr_sensor_device_driver.c
@@ -0,0 +1,220 @@
+/*
+ * An curr_sensor_device_driver driver for current devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "device_driver_common.h"
+#include "curr_sensor_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define CURR_SENSOR_INFO(fmt, args...) LOG_INFO("curr_sensor: ", fmt, ##args)
+#define CURR_SENSOR_ERR(fmt, args...) LOG_ERR("curr_sensor: ", fmt, ##args)
+#define CURR_SENSOR_DBG(fmt, args...) LOG_DBG("curr_sensor: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/*************************************main board current***************************************/
+static int wb_get_main_board_curr_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_curr_number);
+
+ ret = g_drv->get_main_board_curr_number();
+ return ret;
+}
+
+/*
+ * wb_get_main_board_curr_alias - Used to identify the location of the current sensor,
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_curr_alias(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_curr_alias);
+
+ ret = g_drv->get_main_board_curr_alias(curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_curr_type - Used to get the model of current sensor,
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_curr_type(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_curr_type);
+
+ ret = g_drv->get_main_board_curr_type(curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_curr_max - Used to get the maximum threshold of current sensor
+ * filled the value to buf, the value is integer with mA
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_curr_max(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_curr_max);
+
+ ret = g_drv->get_main_board_curr_max(curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_curr_min - Used to get the minimum threshold of current sensor
+ * filled the value to buf, the value is integer with mA
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_curr_min(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_curr_min);
+
+ ret = g_drv->get_main_board_curr_min(curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_curr_value - Used to get the input value of current sensor
+ * filled the value to buf, the value is integer with mA
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_curr_value(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_curr_value);
+
+ ret = g_drv->get_main_board_curr_value(curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_curr_monitor_flag - Used to get the monitor flag of current sensor
+ * filled the value to buf, the value is integer with mA
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_curr_monitor_flag(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_curr_monitor_flag);
+
+ ret = g_drv->get_main_board_curr_monitor_flag(curr_index, buf, count);
+ return ret;
+}
+/*********************************end of main board current************************************/
+
+static struct s3ip_sysfs_curr_sensor_drivers_s drivers = {
+ /*
+ * set ODM current sensor drivers to /sys/s3ip/curr_sensor,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_main_board_curr_number = wb_get_main_board_curr_number,
+ .get_main_board_curr_alias = wb_get_main_board_curr_alias,
+ .get_main_board_curr_type = wb_get_main_board_curr_type,
+ .get_main_board_curr_max = wb_get_main_board_curr_max,
+ .get_main_board_curr_min = wb_get_main_board_curr_min,
+ .get_main_board_curr_value = wb_get_main_board_curr_value,
+ .get_main_board_curr_monitor_flag = wb_get_main_board_curr_monitor_flag,
+};
+
+static int __init curr_sensor_dev_drv_init(void)
+{
+ int ret;
+
+ CURR_SENSOR_INFO("curr_sensor_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_curr_sensor_drivers_register(&drivers);
+ if (ret < 0) {
+ CURR_SENSOR_ERR("curr sensor drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+
+ CURR_SENSOR_INFO("curr_sensor_init success.\n");
+ return 0;
+}
+
+static void __exit curr_sensor_dev_drv_exit(void)
+{
+ s3ip_sysfs_curr_sensor_drivers_unregister();
+ CURR_SENSOR_INFO("curr_sensor_exit success.\n");
+ return;
+}
+
+module_init(curr_sensor_dev_drv_init);
+module_exit(curr_sensor_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("current sensors device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/eeprom_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/eeprom_device_driver.c
new file mode 100644
index 000000000000..ee5d3495ed19
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/eeprom_device_driver.c
@@ -0,0 +1,209 @@
+/*
+ * An eeprom_device_driver driver for eeprom devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "device_driver_common.h"
+#include "eeprom_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define EEPROM_INFO(fmt, args...) LOG_INFO("eeprom: ", fmt, ##args)
+#define EEPROM_ERR(fmt, args...) LOG_ERR("eeprom: ", fmt, ##args)
+#define EEPROM_DBG(fmt, args...) LOG_DBG("eeprom: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/*****************************************eeprom*******************************************/
+
+/*
+ * wb_get_eeprom_number - Used to get eeprom number
+ *
+ * This function returns the size of eeprom by your switch,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_get_eeprom_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eeprom_number);
+
+ ret = g_drv->get_eeprom_number();
+ return ret;
+}
+
+/*
+ * wb_get_eeprom_size - Used to get eeprom size
+ *
+ * This function returns the size of eeprom by your switch,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_get_eeprom_size(unsigned int e2_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eeprom_size);
+
+ ret = g_drv->get_eeprom_size(e2_index);
+ return ret;
+}
+
+/*
+ * wb_get_eeprom_alias - Used to get eeprom alias
+ *
+ * This function returns the size of eeprom by your switch,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eeprom_alias(unsigned int e2_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eeprom_alias);
+
+ ret = g_drv->get_eeprom_alias(e2_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eeprom_tag - Used to get eeprom tag
+ *
+ * This function returns the size of eeprom by your switch,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eeprom_tag(unsigned int e2_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eeprom_tag);
+
+ ret = g_drv->get_eeprom_tag(e2_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eeprom_type - Used to get eeprom type
+ *
+ * This function returns the size of eeprom by your switch,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eeprom_type(unsigned int e2_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eeprom_type);
+
+ ret = g_drv->get_eeprom_type(e2_index, buf, count);
+ return ret;
+}
+
+
+/*
+ * wb_read_eeprom_data - Used to read eeprom data,
+ * @buf: Data read buffer
+ * @offset: offset address to read eeprom data
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_read_eeprom_data(unsigned int e2_index, char *buf, loff_t offset, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->read_eeprom_data);
+
+ ret = g_drv->read_eeprom_data(e2_index, buf, offset, count);
+ return ret;
+}
+
+/*
+ * wb_write_eeprom_data - Used to write eeprom data
+ * @buf: Data write buffer
+ * @offset: offset address to write eeprom data
+ * @count: length of buf
+ *
+ * This function returns the written length of eeprom,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_write_eeprom_data(unsigned int e2_index, char *buf, loff_t offset, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->write_eeprom_data);
+
+ ret = g_drv->write_eeprom_data(e2_index, buf, offset, count);
+ return ret;
+}
+/*************************************end of eeprom****************************************/
+
+static struct s3ip_sysfs_eeprom_drivers_s drivers = {
+ /*
+ * set ODM eeprom drivers to /sys/s3ip/eeprom,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_eeprom_number = wb_get_eeprom_number,
+ .get_eeprom_alias = wb_get_eeprom_alias,
+ .get_eeprom_tag = wb_get_eeprom_tag,
+ .get_eeprom_type = wb_get_eeprom_type,
+ .get_eeprom_size = wb_get_eeprom_size,
+ .read_eeprom_data = wb_read_eeprom_data,
+ .write_eeprom_data = wb_write_eeprom_data,
+};
+
+static int __init eeprom_dev_drv_init(void)
+{
+ int ret;
+
+ EEPROM_INFO("eeprom_dev_drv_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_eeprom_drivers_register(&drivers);
+ if (ret < 0) {
+ EEPROM_ERR("eeprom drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ EEPROM_INFO("eeprom_dev_drv_init success.\n");
+ return 0;
+}
+
+static void __exit eeprom_dev_drv_exit(void)
+{
+ s3ip_sysfs_eeprom_drivers_unregister();
+ EEPROM_INFO("eeprom_exit success.\n");
+ return;
+}
+
+module_init(eeprom_dev_drv_init);
+module_exit(eeprom_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("eeprom device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/fan_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/fan_device_driver.c
new file mode 100644
index 000000000000..5360043678db
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/fan_device_driver.c
@@ -0,0 +1,542 @@
+/*
+ * An fan_device_driver driver for fan devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "device_driver_common.h"
+#include "fan_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define FAN_INFO(fmt, args...) LOG_INFO("fan: ", fmt, ##args)
+#define FAN_ERR(fmt, args...) LOG_ERR("fan: ", fmt, ##args)
+#define FAN_DBG(fmt, args...) LOG_DBG("fan: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/********************************************fan**********************************************/
+static int wb_get_fan_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_number);
+
+ ret = g_drv->get_fan_number();
+ return ret;
+}
+
+static int wb_get_fan_motor_number(unsigned int fan_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_motor_number);
+
+ ret = g_drv->get_fan_motor_number(fan_index);
+ return ret;
+}
+
+/*
+ * wb_get_fan_model_name - Used to get fan model name,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_model_name(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_model_name);
+
+ ret = g_drv->get_fan_model_name(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_vendor - Used to get vendor,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_vendor(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_vendor);
+
+ ret = g_drv->get_fan_vendor(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_serial_number - Used to get fan serial number,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_serial_number(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_serial_number);
+
+ ret = g_drv->get_fan_serial_number(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_part_number - Used to get fan part number,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_part_number(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_part_number);
+
+ ret = g_drv->get_fan_part_number(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_hardware_version - Used to get fan hardware version,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_hardware_version(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_hardware_version);
+
+ ret = g_drv->get_fan_hardware_version(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_status - Used to get fan status,
+ * filled the value to buf, fan status define as below:
+ * 0: ABSENT
+ * 1: OK
+ * 2: NOT OK
+ *
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_status(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_status);
+
+ ret = g_drv->get_fan_status(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_present - Used to get fan present status,
+ * filled the value to buf, fan status define as below:
+ * 0: ABSENT
+ * 1: PRESENT
+ *
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_present(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_present);
+
+ ret = g_drv->get_fan_present(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_led_status - Used to get fan led status
+ * filled the value to buf, led status value define as below:
+ * 0: dark
+ * 1: green
+ * 2: yellow
+ * 3: red
+ * 4:blue
+ * 5: green light flashing
+ * 6: yellow light flashing
+ * 7: red light flashing
+ * 8:blue light flashing
+ *
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_led_status(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_led_status);
+
+ ret = g_drv->get_fan_led_status(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_fan_led_status - Used to set fan led status
+ * @fan_index: start with 1
+ * @status: led status, led status value define as below:
+ * 0: dark
+ * 1: green
+ * 2: yellow
+ * 3: red
+ * 4: blue
+ * 5: green light flashing
+ * 6: yellow light flashing
+ * 7: red light flashing
+ * 8: blue light flashing
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_fan_led_status(unsigned int fan_index, int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_fan_led_status);
+
+ ret = g_drv->set_fan_led_status(fan_index, status);
+ return ret;
+}
+
+/*
+ * wb_get_fan_direction - Used to get fan air flow direction,
+ * filled the value to buf, air flow direction define as below:
+ * 0: F2B
+ * 1: B2F
+ *
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_direction(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_direction);
+
+ ret = g_drv->get_fan_direction(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_motor_status - Used to get fan motor status
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_motor_status(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_motor_status);
+
+ ret = g_drv->get_fan_motor_status(fan_index, motor_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_motor_speed - Used to get fan motor speed
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_motor_speed(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_motor_speed);
+
+ ret = g_drv->get_fan_motor_speed(fan_index, motor_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_motor_speed_tolerance - Used to get fan motor speed tolerance
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_motor_speed_tolerance(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_motor_speed_tolerance);
+
+ ret = g_drv->get_fan_motor_speed_tolerance(fan_index, motor_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_motor_speed_target - Used to get fan motor speed target
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_motor_speed_target(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_motor_speed_target);
+
+ ret = g_drv->get_fan_motor_speed_target(fan_index, motor_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_motor_speed_max - Used to get the maximum threshold of fan motor
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_motor_speed_max(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_motor_speed_max);
+
+ ret = g_drv->get_fan_motor_speed_max(fan_index, motor_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_motor_speed_min - Used to get the minimum threshold of fan motor
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_motor_speed_min(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_motor_speed_min);
+
+ ret = g_drv->get_fan_motor_speed_min(fan_index, motor_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_fan_ratio - Used to get the ratio of fan
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_fan_ratio(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_fan_ratio);
+
+ ret = g_drv->get_fan_ratio(fan_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_fan_ratio - Used to set the ratio of fan
+ * @fan_index: start with 1
+ * @ratio: motor speed ratio, from 0 to 100
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_fan_ratio(unsigned int fan_index, int ratio)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_fan_ratio);
+
+ ret = g_drv->set_fan_ratio(fan_index, ratio);
+ return ret;
+}
+/****************************************end of fan*******************************************/
+
+static struct s3ip_sysfs_fan_drivers_s drivers = {
+ /*
+ * set ODM fan drivers to /sys/s3ip/fan,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_fan_number = wb_get_fan_number,
+ .get_fan_motor_number = wb_get_fan_motor_number,
+ .get_fan_model_name = wb_get_fan_model_name,
+ .get_fan_vendor = wb_get_fan_vendor,
+ .get_fan_serial_number = wb_get_fan_serial_number,
+ .get_fan_part_number = wb_get_fan_part_number,
+ .get_fan_hardware_version = wb_get_fan_hardware_version,
+ .get_fan_status = wb_get_fan_status,
+ .get_fan_present = wb_get_fan_present,
+ .get_fan_led_status = wb_get_fan_led_status,
+ .set_fan_led_status = wb_set_fan_led_status,
+ .get_fan_direction = wb_get_fan_direction,
+ .get_fan_motor_status = wb_get_fan_motor_status,
+ .get_fan_motor_speed = wb_get_fan_motor_speed,
+ .get_fan_motor_speed_tolerance = wb_get_fan_motor_speed_tolerance,
+ .get_fan_motor_speed_target = wb_get_fan_motor_speed_target,
+ .get_fan_motor_speed_max = wb_get_fan_motor_speed_max,
+ .get_fan_motor_speed_min = wb_get_fan_motor_speed_min,
+ .get_fan_ratio = wb_get_fan_ratio,
+ .set_fan_ratio = wb_set_fan_ratio
+};
+
+static int __init fan_dev_drv_init(void)
+{
+ int ret;
+
+ FAN_INFO("fan_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_fan_drivers_register(&drivers);
+ if (ret < 0) {
+ FAN_ERR("fan drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+
+ FAN_INFO("fan_init success.\n");
+ return 0;
+}
+
+static void __exit fan_dev_drv_exit(void)
+{
+ s3ip_sysfs_fan_drivers_unregister();
+ FAN_INFO("fan_exit success.\n");
+ return;
+}
+
+module_init(fan_dev_drv_init);
+module_exit(fan_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("fan device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/fpga_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/fpga_device_driver.c
new file mode 100644
index 000000000000..7fda8b9b7184
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/fpga_device_driver.c
@@ -0,0 +1,216 @@
+/*
+ * An fpga_device_driver driver for fpga devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "device_driver_common.h"
+#include "fpga_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define FPGA_INFO(fmt, args...) LOG_INFO("fpga: ", fmt, ##args)
+#define FPGA_ERR(fmt, args...) LOG_ERR("fpga: ", fmt, ##args)
+#define FPGA_DBG(fmt, args...) LOG_DBG("fpga: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/******************************************FPGA***********************************************/
+static int wb_get_main_board_fpga_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_fpga_number);
+
+ ret = g_drv->get_main_board_fpga_number();
+ return ret;
+}
+
+/*
+ * wb_get_main_board_fpga_alias - Used to identify the location of fpga,
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_fpga_alias(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_fpga_alias);
+
+ ret = g_drv->get_main_board_fpga_alias(fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_fpga_type - Used to get fpga model name
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_fpga_type(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_fpga_type);
+
+ ret = g_drv->get_main_board_fpga_type(fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_fpga_firmware_version - Used to get fpga firmware version,
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_fpga_firmware_version(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_fpga_firmware_version);
+
+ ret = g_drv->get_main_board_fpga_firmware_version(fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_fpga_board_version - Used to get fpga board version,
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_fpga_board_version(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_fpga_board_version);
+
+ ret = g_drv->get_main_board_fpga_board_version(fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_fpga_test_reg - Used to test fpga register read
+ * filled the value to buf, value is hexadecimal, start with 0x
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_fpga_test_reg(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_fpga_test_reg);
+
+ ret = g_drv->get_main_board_fpga_test_reg(fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_main_board_fpga_test_reg - Used to test fpga register write
+ * @fpga_index: start with 1
+ * @value: value write to fpga
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_main_board_fpga_test_reg(unsigned int fpga_index, unsigned int value)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_main_board_fpga_test_reg);
+
+ ret = g_drv->set_main_board_fpga_test_reg(fpga_index, value);
+ return ret;
+}
+/***************************************end of FPGA*******************************************/
+
+static struct s3ip_sysfs_fpga_drivers_s drivers = {
+ /*
+ * set ODM FPGA drivers to /sys/s3ip/fpga,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_main_board_fpga_number = wb_get_main_board_fpga_number,
+ .get_main_board_fpga_alias = wb_get_main_board_fpga_alias,
+ .get_main_board_fpga_type = wb_get_main_board_fpga_type,
+ .get_main_board_fpga_firmware_version = wb_get_main_board_fpga_firmware_version,
+ .get_main_board_fpga_board_version = wb_get_main_board_fpga_board_version,
+ .get_main_board_fpga_test_reg = wb_get_main_board_fpga_test_reg,
+ .set_main_board_fpga_test_reg = wb_set_main_board_fpga_test_reg,
+};
+
+static int __init fpga_dev_drv_init(void)
+{
+ int ret;
+
+ FPGA_INFO("fpga_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_fpga_drivers_register(&drivers);
+ if (ret < 0) {
+ FPGA_ERR("fpga drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ FPGA_INFO("fpga_init success.\n");
+ return 0;
+}
+
+static void __exit fpga_dev_drv_exit(void)
+{
+ s3ip_sysfs_fpga_drivers_unregister();
+ FPGA_INFO("fpga_exit success.\n");
+ return;
+}
+
+module_init(fpga_dev_drv_init);
+module_exit(fpga_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("fpga device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/include/device_driver_common.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/include/device_driver_common.h
new file mode 100644
index 000000000000..5628c298b9c9
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/include/device_driver_common.h
@@ -0,0 +1,69 @@
+/*
+ * A header definition for devcie_driver_common driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DEVICE_DRIVER_COMMON_H_
+#define _DEVICE_DRIVER_COMMON_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+enum LOG_LEVEL {
+ INFO = 0x1,
+ ERR = 0x2,
+ DBG = 0x4,
+ ALL = 0xf
+};
+
+#define LOG_INFO(_prefix, fmt, args...) do { \
+ if (g_loglevel & INFO) { \
+ printk(KERN_INFO _prefix "%s "fmt, __FUNCTION__, ##args); \
+ } \
+} while (0)
+
+#define LOG_ERR(_prefix, fmt, args...) do { \
+ if (g_loglevel & ERR) { \
+ printk(KERN_ERR _prefix "%s "fmt, __FUNCTION__, ##args); \
+ } \
+} while (0)
+
+#define LOG_DBG(_prefix, fmt, args...) do { \
+ if (g_loglevel & DBG) { \
+ printk(KERN_DEBUG _prefix "%s "fmt, __FUNCTION__, ##args); \
+ } \
+} while (0)
+
+#define check_pfun(p) do { \
+ if (p == NULL) { \
+ if (g_loglevel & ERR) { \
+ printk(KERN_ERR "%s, %s is NULL.\n", __FUNCTION__, #p); \
+ } \
+ return -ENOSYS; \
+ } \
+} while (0)
+
+#define check_p(p) check_pfun(p)
+
+#endif /* _DEVICE_DRIVER_COMMON_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/psu_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/psu_device_driver.c
new file mode 100644
index 000000000000..c97f4814523d
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/psu_device_driver.c
@@ -0,0 +1,1025 @@
+/*
+ * An psu_device_driver driver for psu devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include
+
+#include "device_driver_common.h"
+#include "psu_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define PSU_INFO(fmt, args...) LOG_INFO("psu: ", fmt, ##args)
+#define PSU_ERR(fmt, args...) LOG_ERR("psu: ", fmt, ##args)
+#define PSU_DBG(fmt, args...) LOG_DBG("psu: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/********************************************psu**********************************************/
+static int wb_get_psu_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_number);
+
+ ret = g_drv->get_psu_number();
+ return ret;
+}
+
+static int wb_get_psu_temp_number(unsigned int psu_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_temp_number);
+
+ ret = g_drv->get_psu_temp_number(psu_index);
+ return ret;
+}
+
+/*
+ * wb_get_psu_model_name - Used to get psu model name,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_model_name(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_model_name);
+
+ ret = g_drv->get_psu_model_name(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_vendor - Used to get psu model name,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_vendor(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_vendor);
+
+ ret = g_drv->get_psu_vendor(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_date - Used to get psu date,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_date(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_date);
+
+ ret = g_drv->get_psu_date(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_status - Used to get psu status,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_status);
+
+ ret = g_drv->get_psu_status(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_hw_status - Used to get psu status,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_hw_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_hw_status);
+
+ ret = g_drv->get_psu_hw_status(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_alarm - Used to get psu alarm status,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_alarm(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_alarm);
+
+ ret = g_drv->get_psu_alarm(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_serial_number - Used to get psu serial number,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_serial_number(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_serial_number);
+
+ ret = g_drv->get_psu_serial_number(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_part_number - Used to get psu part number,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_part_number(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_part_number);
+
+ ret = g_drv->get_psu_part_number(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_hardware_version - Used to get psu hardware version,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_hardware_version(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_hardware_version);
+
+ ret = g_drv->get_psu_hardware_version(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_type - Used to get the input type of psu
+ * filled the value to buf, input type value define as below:
+ * 0: DC
+ * 1: AC
+ *
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_type(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_type);
+
+ ret = g_drv->get_psu_type(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_in_curr - Used to get the input current of psu
+ * filled the value to buf, the value is integer with mA
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_in_curr(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_in_curr);
+
+ ret = g_drv->get_psu_in_curr(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_in_vol - Used to get the input voltage of psu
+ * filled the value to bu, the value is integer with mV
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_in_vol(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_in_vol);
+
+ ret = g_drv->get_psu_in_vol(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_in_power - Used to get the input power of psu
+ * filled the value to buf, the value is integer with uW
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_in_power(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_in_power);
+
+ ret = g_drv->get_psu_in_power(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_out_curr - Used to get the output current of psu
+ * filled the value to buf, the value is integer with mA
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_out_curr(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_out_curr);
+
+ ret = g_drv->get_psu_out_curr(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_out_vol - Used to get the output voltage of psu
+ * filled the value to buf, the value is integer with mV
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_out_vol(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_out_vol);
+
+ ret = g_drv->get_psu_out_vol(psu_index, buf, count);
+ return ret;
+}
+
+static ssize_t wb_get_psu_attr_threshold(unsigned int psu_index, unsigned int type, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_attr_threshold);
+
+ ret = g_drv->get_psu_attr_threshold(psu_index, type, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_out_power - Used to get the output power of psu
+ * filled the value to buf, the value is integer with uW
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_out_power(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_out_power);
+
+ ret = g_drv->get_psu_out_power(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_out_max_power - Used to get the output max power of psu
+ * filled the value to buf, the value is integer with uW
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_out_max_power(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_out_max_power);
+
+ ret = g_drv->get_psu_out_max_power(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_present_status - Used to get psu present status
+ * filled the value to buf, psu present status define as below:
+ * 0: ABSENT
+ * 1: PRESENT
+ *
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_present_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_present_status);
+
+ ret = g_drv->get_psu_present_status(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_in_status - Used to get psu input status
+ * filled the value to buf, psu input status define as below:
+ * 0: NOT OK
+ * 1: OK
+ *
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_in_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_in_status);
+
+ ret = g_drv->get_psu_in_status(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_status_pmbus - Used to get psu status from pmbus
+ * filled the value to buf, psu output status define as below:
+ * 0: NOT OK
+ * 1: OK
+ *
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_status_pmbus(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_status_pmbus);
+
+ ret = g_drv->get_psu_status_pmbus(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_out_status - Used to get psu output status
+ * filled the value to buf, psu output status define as below:
+ * 0: NOT OK
+ * 1: OK
+ *
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_out_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_out_status);
+
+ ret = g_drv->get_psu_out_status(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_fan_speed_cal - Used to get psu fan speed cal
+ * filled the value to buf
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_fan_speed_cal(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_fan_speed_cal);
+
+ ret = g_drv->get_psu_fan_speed_cal(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_fan_speed - Used to get psu fan speed
+ * filled the value to buf
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_fan_speed(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_fan_speed);
+
+ ret = g_drv->get_psu_fan_speed(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_fan_ratio - Used to get the ratio of psu fan
+ * filled the value to buf
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_fan_ratio(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_fan_ratio);
+
+ ret = g_drv->get_psu_fan_ratio(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_psu_fan_ratio - Used to set the ratio of psu fan
+ * @psu_index: start with 1
+ * @ratio: from 0 to 100
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_psu_fan_ratio(unsigned int psu_index, int ratio)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_psu_fan_ratio);
+
+ ret = g_drv->set_psu_fan_ratio(psu_index, ratio);
+ return ret;
+}
+
+/*
+ * wb_get_psu_fan_direction - Used to get psu air flow direction,
+ * filled the value to buf, air flow direction define as below:
+ * 0: F2B
+ * 1: B2F
+ *
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_fan_direction(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_fan_direction);
+
+ ret = g_drv->get_psu_fan_direction(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_led_status - Used to get psu led status
+ * filled the value to buf, led status value define as below:
+ * 0: dark
+ * 1: green
+ * 2: yellow
+ * 3: red
+ * 4: blue
+ * 5: green light flashing
+ * 6: yellow light flashing
+ * 7: red light flashing
+ * 8: blue light flashing
+ *
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_led_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_led_status);
+
+ ret = g_drv->get_psu_led_status(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_temp_alias - Used to identify the location of the temperature sensor of psu,
+ * @psu_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_temp_alias(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_temp_alias);
+
+ ret = g_drv->get_psu_temp_alias(psu_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_temp_type - Used to get the model of temperature sensor of psu,
+ * @psu_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_temp_type(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_temp_type);
+
+ ret = g_drv->get_psu_temp_type(psu_index, temp_index, buf, count);
+ return ret;
+
+}
+
+/*
+ * wb_get_psu_temp_max - Used to get the maximum threshold of temperature sensor of psu,
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @psu_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_temp_max(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_temp_max);
+
+ ret = g_drv->get_psu_temp_max(psu_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_psu_temp_max - Used to set the maximum threshold of temperature sensor of psu,
+ * get value from buf and set it to maximum threshold of psu temperature sensor
+ * @psu_index: start with 1
+ * @temp_index: start with 1
+ * @buf: the buf store the data to be set, eg '80.000'
+ * @count: length of buf
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_psu_temp_max(unsigned int psu_index, unsigned int temp_index,
+ const char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_psu_temp_max);
+
+ ret = g_drv->set_psu_temp_max(psu_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_temp_min - Used to get the minimum threshold of temperature sensor of psu,
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @psu_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_temp_min(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_temp_min);
+
+ ret = g_drv->get_psu_temp_min(psu_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_psu_temp_min - Used to set the minimum threshold of temperature sensor of psu,
+ * get value from buf and set it to minimum threshold of psu temperature sensor
+ * @psu_index: start with 1
+ * @temp_index: start with 1
+ * @buf: the buf store the data to be set, eg '50.000'
+ * @count: length of buf
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_psu_temp_min(unsigned int psu_index, unsigned int temp_index,
+ const char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_psu_temp_min);
+
+ ret = g_drv->set_psu_temp_min(psu_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_temp_value - Used to get the input value of temperature sensor of psu
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @psu_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_temp_value(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_temp_value);
+
+ ret = g_drv->get_psu_temp_value(psu_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_eeprom_size - Used to get psu eeprom size
+ *
+ * This function returns the size of port eeprom,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_get_psu_eeprom_size(unsigned int psu_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_eeprom_size);
+
+ ret = g_drv->get_psu_eeprom_size(psu_index);
+ return ret;
+}
+
+/*
+ * wb_read_psu_eeprom_data - Used to read psu eeprom data,
+ * @buf: Data read buffer
+ * @offset: offset address to read psu eeprom data
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_read_psu_eeprom_data(unsigned int psu_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->read_psu_eeprom_data);
+
+ ret = g_drv->read_psu_eeprom_data(psu_index, buf, offset, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_blackbox_info - Used to get psu blackbox information,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_blackbox_info(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_blackbox_info);
+
+ ret = g_drv->get_psu_blackbox_info(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_psu_pmbus_info - Used to get psu pmbus information,
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_psu_pmbus_info(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_psu_pmbus_info);
+
+ ret = g_drv->get_psu_pmbus_info(psu_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_clear_psu_blackbox - Used to clear psu blackbox information
+ * @psu_index: start with 1
+ * @value: 1
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_clear_psu_blackbox(unsigned int psu_index, uint8_t value)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->clear_psu_blackbox);
+
+ ret = g_drv->clear_psu_blackbox(psu_index, value);
+ return ret;
+}
+
+/****************************************end of psu*******************************************/
+
+static struct s3ip_sysfs_psu_drivers_s drivers = {
+ /*
+ * set ODM psu drivers to /sys/s3ip/psu,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_psu_number = wb_get_psu_number,
+ .get_psu_temp_number = wb_get_psu_temp_number,
+ .get_psu_model_name = wb_get_psu_model_name,
+ .get_psu_vendor = wb_get_psu_vendor,
+ .get_psu_date = wb_get_psu_date,
+ .get_psu_status = wb_get_psu_status,
+ .get_psu_hw_status = wb_get_psu_hw_status,
+ .get_psu_alarm = wb_get_psu_alarm,
+ .get_psu_serial_number = wb_get_psu_serial_number,
+ .get_psu_part_number = wb_get_psu_part_number,
+ .get_psu_hardware_version = wb_get_psu_hardware_version,
+ .get_psu_type = wb_get_psu_type,
+ .get_psu_in_curr = wb_get_psu_in_curr,
+ .get_psu_in_vol = wb_get_psu_in_vol,
+ .get_psu_in_power = wb_get_psu_in_power,
+ .get_psu_out_curr = wb_get_psu_out_curr,
+ .get_psu_out_vol = wb_get_psu_out_vol,
+ .get_psu_out_power = wb_get_psu_out_power,
+ .get_psu_out_max_power = wb_get_psu_out_max_power,
+ .get_psu_present_status = wb_get_psu_present_status,
+ .get_psu_status_pmbus = wb_get_psu_status_pmbus,
+ .get_psu_in_status = wb_get_psu_in_status,
+ .get_psu_out_status = wb_get_psu_out_status,
+ .get_psu_fan_speed = wb_get_psu_fan_speed,
+ .get_psu_fan_ratio = wb_get_psu_fan_ratio,
+ .set_psu_fan_ratio = wb_set_psu_fan_ratio,
+ .get_psu_fan_direction = wb_get_psu_fan_direction,
+ .get_psu_led_status = wb_get_psu_led_status,
+ .get_psu_temp_alias = wb_get_psu_temp_alias,
+ .get_psu_temp_type = wb_get_psu_temp_type,
+ .get_psu_temp_max = wb_get_psu_temp_max,
+ .set_psu_temp_max = wb_set_psu_temp_max,
+ .get_psu_temp_min = wb_get_psu_temp_min,
+ .set_psu_temp_min = wb_set_psu_temp_min,
+ .get_psu_temp_value = wb_get_psu_temp_value,
+ .get_psu_fan_speed_cal = wb_get_psu_fan_speed_cal,
+ .get_psu_attr_threshold = wb_get_psu_attr_threshold,
+ .get_psu_eeprom_size = wb_get_psu_eeprom_size,
+ .read_psu_eeprom_data = wb_read_psu_eeprom_data,
+ .get_psu_blackbox_info = wb_get_psu_blackbox_info,
+ .get_psu_pmbus_info = wb_get_psu_pmbus_info,
+ .clear_psu_blackbox = wb_clear_psu_blackbox,
+};
+
+static int __init psu_dev_drv_init(void)
+{
+ int ret;
+
+ PSU_INFO("psu_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_psu_drivers_register(&drivers);
+ if (ret < 0) {
+ PSU_ERR("psu drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ PSU_INFO("psu_init success.\n");
+ return 0;
+}
+
+static void __exit psu_dev_drv_exit(void)
+{
+ s3ip_sysfs_psu_drivers_unregister();
+ PSU_INFO("psu_exit ok.\n");
+
+ return;
+}
+
+module_init(psu_dev_drv_init);
+module_exit(psu_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("psu device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/slot_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/slot_device_driver.c
new file mode 100644
index 000000000000..f22e51e1613e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/slot_device_driver.c
@@ -0,0 +1,1100 @@
+/*
+ * An slot_device_driver driver for slot devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include
+
+#include "device_driver_common.h"
+#include "slot_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define SLOT_INFO(fmt, args...) LOG_INFO("slot: ", fmt, ##args)
+#define SLOT_ERR(fmt, args...) LOG_ERR("slot: ", fmt, ##args)
+#define SLOT_DBG(fmt, args...) LOG_DBG("slot: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/******************************************slot***********************************************/
+static int wb_get_slot_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_number);
+
+ ret = g_drv->get_slot_number();
+ return ret;
+}
+
+static int wb_get_slot_temp_number(unsigned int slot_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_temp_number);
+
+ ret = g_drv->get_slot_temp_number(slot_index);
+ return ret;
+}
+
+static int wb_get_slot_vol_number(unsigned int slot_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_number);
+
+ ret = g_drv->get_slot_vol_number(slot_index);
+ return ret;
+}
+
+static int wb_get_slot_curr_number(unsigned int slot_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_curr_number);
+
+ ret = g_drv->get_slot_curr_number(slot_index);
+ return ret;
+}
+
+static int wb_get_slot_fpga_number(unsigned int slot_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_fpga_number);
+
+ ret = g_drv->get_slot_fpga_number(slot_index);
+ return ret;
+}
+
+static int wb_get_slot_cpld_number(unsigned int slot_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_cpld_number);
+
+ ret = g_drv->get_slot_cpld_number(slot_index);
+ return ret;
+}
+
+/*
+ * wb_get_slot_model_name - Used to get slot model name,
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_model_name(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_model_name);
+
+ ret = g_drv->get_slot_model_name(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vendor - Used to get slot model name,
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vendor(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vendor);
+
+ ret = g_drv->get_slot_vendor(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_serial_number - Used to get slot serial number,
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_serial_number(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_serial_number);
+
+ ret = g_drv->get_slot_serial_number(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_part_number - Used to get slot part number,
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_part_number(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_part_number);
+
+ ret = g_drv->get_slot_part_number(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_hardware_version - Used to get slot hardware version,
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_hardware_version(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_hardware_version);
+
+ ret = g_drv->get_slot_hardware_version(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_status - Used to get slot status,
+ * filled the value to buf, slot status define as below:
+ * 0: ABSENT
+ * 1: OK
+ * 2: NOT OK
+ *
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_status(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_status);
+
+ ret = g_drv->get_slot_status(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_led_status - Used to get slot led status
+ * filled the value to buf, led status value define as below:
+ * 0: dark
+ * 1: green
+ * 2: yellow
+ * 3: red
+ * 4: blue
+ * 5: green light flashing
+ * 6: yellow light flashing
+ * 7: red light flashing
+ * 8: blue light flashing
+ *
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_led_status(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_led_status);
+
+ ret = g_drv->get_slot_led_status(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_slot_led_status - Used to set slot led status
+ * @slot_index: start with 1
+ * @status: led status, led status value define as below:
+ * 0: dark
+ * 1: green
+ * 2: yellow
+ * 3: red
+ * 4:blue
+ * 5: green light flashing
+ * 6: yellow light flashing
+ * 7: red light flashing
+ * 8:blue light flashing
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_slot_led_status(unsigned int slot_index, int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_slot_led_status);
+
+ ret = g_drv->set_slot_led_status(slot_index, status);
+ return ret;
+}
+
+/*
+ * wb_set_slot_power_status - Used to set slot power status,
+ * filled the value to buf, slot status define as below:
+ * 0: OFF
+ * 1: ON
+ *
+ * @slot_index: start with 1
+ * @status: power status
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_slot_power_status(unsigned int slot_index, int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_slot_power_status);
+
+ ret = g_drv->set_slot_power_status(slot_index, status);
+ return ret;
+}
+
+/*
+ * wb_get_slot_power_status - Used to get slot power status,
+ * filled the value to buf, slot status define as below:
+ * 0: OFF
+ * 1: ON
+ *
+ * @slot_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_power_status(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_power_status);
+
+ ret = g_drv->get_slot_power_status(slot_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_temp_alias - Used to identify the location of the temperature sensor of slot,
+ * @slot_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_temp_alias(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_temp_alias);
+
+ ret = g_drv->get_slot_temp_alias(slot_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_temp_type - Used to get the model of temperature sensor of slot,
+ * @slot_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_temp_type(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_temp_type);
+
+ ret = g_drv->get_slot_temp_type(slot_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_temp_max - Used to get the maximum threshold of temperature sensor of slot,
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @slot_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_temp_max(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_temp_max);
+
+ ret = g_drv->get_slot_temp_max(slot_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_temp_min - Used to get the minimum threshold of temperature sensor of slot,
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @slot_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_temp_min(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_temp_min);
+
+ ret = g_drv->get_slot_temp_min(slot_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_temp_value - Used to get the input value of temperature sensor of slot,
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @slot_index: start with 1
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_temp_value(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_temp_value);
+
+ ret = g_drv->get_slot_temp_value(slot_index, temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vol_alias - Used to identify the location of the voltage sensor of slot,
+ * @slot_index: start with 1
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vol_alias(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_alias);
+
+ ret = g_drv->get_slot_vol_alias(slot_index, vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vol_type - Used to get the model of voltage sensor of slot,
+ * such as udc90160, tps53622 and so on
+ * @slot_index: start with 1
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vol_type(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_type);
+
+ ret = g_drv->get_slot_vol_type(slot_index, vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vol_max - Used to get the maximum threshold of voltage sensor of slot,
+ * filled the value to buf, the value is integer with mV
+ * @slot_index: start with 1
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vol_max(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_max);
+
+ ret = g_drv->get_slot_vol_max(slot_index, vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vol_min - Used to get the minimum threshold of voltage sensor of slot,
+ * filled the value to buf, the value is integer with mV
+ * @slot_index: start with 1
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vol_min(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_min);
+
+ ret = g_drv->get_slot_vol_min(slot_index, vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vol_range - Used to get the output error value of voltage sensor of slot,
+ * filled the value to buf
+ * @slot_index: start with 1
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vol_range(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_range);
+
+ ret = g_drv->get_slot_vol_range(slot_index, vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vol_nominal_value - Used to get the nominal value of voltage sensor of slot,
+ * filled the value to buf
+ * @slot_index: start with 1
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vol_nominal_value(unsigned int slot_index,
+ unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_nominal_value);
+
+ ret = g_drv->get_slot_vol_nominal_value(slot_index, vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_vol_value - Used to get the input value of voltage sensor of slot,
+ * filled the value to buf, the value is integer with mV
+ * @slot_index: start with 1
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_vol_value(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_vol_value);
+
+ ret = g_drv->get_slot_vol_value(slot_index, vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_curr_alias - Used to identify the location of the current sensor of slot,
+ * @slot_index: start with 1
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_curr_alias(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_curr_alias);
+
+ ret = g_drv->get_slot_curr_alias(slot_index, curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_curr_type - Used to get the model of current sensor of slot,
+ * @slot_index: start with 1
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_curr_type(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_curr_type);
+
+ ret = g_drv->get_slot_curr_type(slot_index, curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_curr_max - Used to get the maximum threshold of current sensor of slot,
+ * filled the value to buf, the value is integer with mA
+ * @slot_index: start with 1
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_curr_max(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_curr_max);
+
+ ret = g_drv->get_slot_curr_max(slot_index, curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_curr_min - Used to get the minimum threshold of current sensor of slot,
+ * filled the value to buf, the value is integer with mA
+ * @slot_index: start with 1
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_curr_min(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_curr_min);
+
+ ret = g_drv->get_slot_curr_min(slot_index, curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_curr_value - Used to get the input value of current sensor of slot,
+ * filled the value to buf, the value is integer with mA
+ * @slot_index: start with 1
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_curr_value(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_curr_value);
+
+ ret = g_drv->get_slot_curr_value(slot_index, curr_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_fpga_alias - Used to identify the location of slot fpga,
+ * @slot_index: start with 1
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_fpga_alias(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_fpga_alias);
+
+ ret = g_drv->get_slot_fpga_alias(slot_index, fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_fpga_type - Used to get slot fpga model name
+ * @slot_index: start with 1
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_fpga_type(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_fpga_type);
+
+ ret = g_drv->get_slot_fpga_type(slot_index, fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_fpga_firmware_version - Used to get slot fpga firmware version,
+ * @slot_index: start with 1
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_fpga_firmware_version(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_fpga_firmware_version);
+
+ ret = g_drv->get_slot_fpga_firmware_version(slot_index, fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_fpga_board_version - Used to get slot fpga board version,
+ * @slot_index: start with 1
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_fpga_board_version(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_fpga_board_version);
+
+ ret = g_drv->get_slot_fpga_board_version(slot_index, fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_fpga_test_reg - Used to test slot fpga register read
+ * filled the value to buf, value is hexadecimal, start with 0x
+ * @slot_index: start with 1
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_fpga_test_reg(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_fpga_test_reg);
+
+ ret = g_drv->get_slot_fpga_test_reg(slot_index, fpga_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_slot_fpga_test_reg - Used to test slot fpga register write
+ * @slot_index: start with 1
+ * @fpga_index: start with 1
+ * @value: value write to slot fpga
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_slot_fpga_test_reg(unsigned int slot_index, unsigned int fpga_index,
+ unsigned int value)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_slot_fpga_test_reg);
+
+ ret = g_drv->set_slot_fpga_test_reg(slot_index, fpga_index, value);
+ return ret;
+}
+
+/*
+ * wb_get_slot_cpld_alias - Used to identify the location of slot cpld,
+ * @slot_index: start with 1
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_cpld_alias(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_cpld_alias);
+
+ ret = g_drv->get_slot_cpld_alias(slot_index, cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_cpld_type - Used to get slot cpld model name
+ * @slot_index: start with 1
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_cpld_type(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_cpld_type);
+
+ ret = g_drv->get_slot_cpld_type(slot_index, cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_cpld_firmware_version - Used to get slot cpld firmware version,
+ * @slot_index: start with 1
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_cpld_firmware_version(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_cpld_firmware_version);
+
+ ret = g_drv->get_slot_cpld_firmware_version(slot_index, cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_cpld_board_version - Used to get slot cpld board version,
+ * @slot_index: start with 1
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_cpld_board_version(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_cpld_board_version);
+
+ ret = g_drv->get_slot_cpld_board_version(slot_index, cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_slot_cpld_test_reg - Used to test slot cpld register read
+ * filled the value to buf, value is hexadecimal, start with 0x
+ * @slot_index: start with 1
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_slot_cpld_test_reg(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_slot_cpld_test_reg);
+
+ ret = g_drv->get_slot_cpld_test_reg(slot_index, cpld_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_slot_cpld_test_reg - Used to test slot cpld register write
+ * @slot_index: start with 1
+ * @cpld_index: start with 1
+ * @value: value write to slot cpld
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_slot_cpld_test_reg(unsigned int slot_index, unsigned int cpld_index,
+ unsigned int value)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_slot_cpld_test_reg);
+
+ ret = g_drv->set_slot_cpld_test_reg(slot_index, cpld_index, value);
+ return ret;
+}
+/***************************************end of slot*******************************************/
+
+static struct s3ip_sysfs_slot_drivers_s drivers = {
+ /*
+ * set ODM slot drivers to /sys/s3ip/slot,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_slot_number = wb_get_slot_number,
+ .get_slot_temp_number = wb_get_slot_temp_number,
+ .get_slot_vol_number = wb_get_slot_vol_number,
+ .get_slot_curr_number = wb_get_slot_curr_number,
+ .get_slot_cpld_number = wb_get_slot_cpld_number,
+ .get_slot_fpga_number = wb_get_slot_fpga_number,
+ .get_slot_model_name = wb_get_slot_model_name,
+ .get_slot_vendor = wb_get_slot_vendor,
+ .get_slot_serial_number = wb_get_slot_serial_number,
+ .get_slot_part_number = wb_get_slot_part_number,
+ .get_slot_hardware_version = wb_get_slot_hardware_version,
+ .get_slot_status = wb_get_slot_status,
+ .get_slot_led_status = wb_get_slot_led_status,
+ .set_slot_led_status = wb_set_slot_led_status,
+ .get_slot_power_status = wb_get_slot_power_status,
+ .set_slot_power_status = wb_set_slot_power_status,
+ .get_slot_temp_alias = wb_get_slot_temp_alias,
+ .get_slot_temp_type = wb_get_slot_temp_type,
+ .get_slot_temp_max = wb_get_slot_temp_max,
+ .get_slot_temp_min = wb_get_slot_temp_min,
+ .get_slot_temp_value = wb_get_slot_temp_value,
+ .get_slot_vol_alias = wb_get_slot_vol_alias,
+ .get_slot_vol_type = wb_get_slot_vol_type,
+ .get_slot_vol_max = wb_get_slot_vol_max,
+ .get_slot_vol_min = wb_get_slot_vol_min,
+ .get_slot_vol_range = wb_get_slot_vol_range,
+ .get_slot_vol_nominal_value = wb_get_slot_vol_nominal_value,
+ .get_slot_vol_value = wb_get_slot_vol_value,
+ .get_slot_curr_alias = wb_get_slot_curr_alias,
+ .get_slot_curr_type = wb_get_slot_curr_type,
+ .get_slot_curr_max = wb_get_slot_curr_max,
+ .get_slot_curr_min = wb_get_slot_curr_min,
+ .get_slot_curr_value = wb_get_slot_curr_value,
+ .get_slot_fpga_alias = wb_get_slot_fpga_alias,
+ .get_slot_fpga_alias = wb_get_slot_fpga_alias,
+ .get_slot_fpga_type = wb_get_slot_fpga_type,
+ .get_slot_fpga_firmware_version = wb_get_slot_fpga_firmware_version,
+ .get_slot_fpga_board_version = wb_get_slot_fpga_board_version,
+ .get_slot_fpga_test_reg = wb_get_slot_fpga_test_reg,
+ .set_slot_fpga_test_reg = wb_set_slot_fpga_test_reg,
+ .get_slot_cpld_alias = wb_get_slot_cpld_alias,
+ .get_slot_cpld_type = wb_get_slot_cpld_type,
+ .get_slot_cpld_firmware_version = wb_get_slot_cpld_firmware_version,
+ .get_slot_cpld_board_version = wb_get_slot_cpld_board_version,
+ .get_slot_cpld_test_reg = wb_get_slot_cpld_test_reg,
+ .set_slot_cpld_test_reg = wb_set_slot_cpld_test_reg,
+};
+
+static int __init slot_dev_drv_init(void)
+{
+ int ret;
+
+ SLOT_INFO("slot_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_slot_drivers_register(&drivers);
+ if (ret < 0) {
+ SLOT_ERR("slot drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ SLOT_INFO("slot_init success.\n");
+ return 0;
+}
+
+static void __exit slot_dev_drv_exit(void)
+{
+ s3ip_sysfs_slot_drivers_unregister();
+ SLOT_INFO("slot_exit success.\n");
+ return;
+}
+
+module_init(slot_dev_drv_init);
+module_exit(slot_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("slot device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/syseeprom_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/syseeprom_device_driver.c
new file mode 100644
index 000000000000..c431c5dbb703
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/syseeprom_device_driver.c
@@ -0,0 +1,136 @@
+/*
+ * An syseeprom_device_driver driver for syseeprom devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include
+
+#include "device_driver_common.h"
+#include "syseeprom_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define SYSE2_INFO(fmt, args...) LOG_INFO("syseeprom: ", fmt, ##args)
+#define SYSE2_ERR(fmt, args...) LOG_ERR("syseeprom: ", fmt, ##args)
+#define SYSE2_DBG(fmt, args...) LOG_DBG("syseeprom: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/*****************************************syseeprom*******************************************/
+/*
+ * wb_get_syseeprom_size - Used to get syseeprom size
+ *
+ * This function returns the size of syseeprom by your switch,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_get_syseeprom_size(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_syseeprom_size);
+
+ ret = g_drv->get_syseeprom_size();
+ return ret;
+}
+
+/*
+ * wb_read_syseeprom_data - Used to read syseeprom data,
+ * @buf: Data read buffer
+ * @offset: offset address to read syseeprom data
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_read_syseeprom_data(char *buf, loff_t offset, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->read_syseeprom_data);
+
+ ret = g_drv->read_syseeprom_data(buf, offset, count);
+ return ret;
+}
+
+/*
+ * wb_write_syseeprom_data - Used to write syseeprom data
+ * @buf: Data write buffer
+ * @offset: offset address to write syseeprom data
+ * @count: length of buf
+ *
+ * This function returns the written length of syseeprom,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_write_syseeprom_data(char *buf, loff_t offset, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->write_syseeprom_data);
+
+ ret = g_drv->write_syseeprom_data(buf, offset, count);
+ return ret;
+}
+/*************************************end of syseeprom****************************************/
+
+static struct s3ip_sysfs_syseeprom_drivers_s drivers = {
+ /*
+ * set ODM syseeprom drivers to /sys/s3ip/syseeprom,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_syseeprom_size = wb_get_syseeprom_size,
+ .read_syseeprom_data = wb_read_syseeprom_data,
+ .write_syseeprom_data = wb_write_syseeprom_data,
+};
+
+static int __init syseeprom_dev_drv_init(void)
+{
+ int ret;
+
+ SYSE2_INFO("syseeprom_dev_drv_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_syseeprom_drivers_register(&drivers);
+ if (ret < 0) {
+ SYSE2_ERR("syseeprom drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ SYSE2_INFO("syseeprom_dev_drv_init success.\n");
+ return 0;
+}
+
+static void __exit syseeprom_dev_drv_exit(void)
+{
+ s3ip_sysfs_syseeprom_drivers_unregister();
+ SYSE2_INFO("syseeprom_exit success.\n");
+ return;
+}
+
+module_init(syseeprom_dev_drv_init);
+module_exit(syseeprom_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("syseeprom device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/sysled_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/sysled_device_driver.c
new file mode 100644
index 000000000000..05da8b680084
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/sysled_device_driver.c
@@ -0,0 +1,240 @@
+/*
+ * An sysled_device_driver driver for sysled devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include
+
+#include "device_driver_common.h"
+#include "sysled_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define SYSLED_INFO(fmt, args...) LOG_INFO("sysled: ", fmt, ##args)
+#define SYSLED_ERR(fmt, args...) LOG_ERR("sysled: ", fmt, ##args)
+#define SYSLED_DBG(fmt, args...) LOG_DBG("sysled: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/*****************************************sysled**********************************************/
+/*
+ * wb_get_sys_led_status - Used to get sys led status
+ * filled the value to buf, led status value define as below:
+ * 0: dark
+ * 1: green
+ * 2: yellow
+ * 3: red
+ * 4: blue
+ * 5: green light flashing
+ * 6: yellow light flashing
+ * 7: red light flashing
+ * 8: blue light flashing
+ *
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_sys_led_status(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_sys_led_status);
+
+ ret = g_drv->get_sys_led_status(buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_sys_led_status - Used to set sys led status
+ * @status: led status, led status value define as below:
+ * 0: dark
+ * 1: green
+ * 2: yellow
+ * 3: red
+ * 4: blue
+ * 5: green light flashing
+ * 6: yellow light flashing
+ * 7: red light flashing
+ * 8: blue light flashing
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_sys_led_status(int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_sys_led_status);
+
+ ret = g_drv->set_sys_led_status(status);
+ return ret;
+}
+
+/* Similar to wb_get_sys_led_status */
+static ssize_t wb_get_bmc_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_bmc_led_status);
+
+ ret = g_drv->get_bmc_led_status(buf, count);
+ return ret;
+}
+
+/* Similar to wb_set_sys_led_status */
+static int wb_set_bmc_led_status(int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_bmc_led_status);
+
+ ret = g_drv->set_bmc_led_status(status);
+ return ret;
+}
+
+/* Similar to wb_get_sys_led_status */
+static ssize_t wb_get_sys_fan_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_sys_fan_led_status);
+
+ ret = g_drv->get_sys_fan_led_status(buf, count);
+ return ret;
+}
+
+/* Similar to wb_set_sys_led_status */
+static int wb_set_sys_fan_led_status(int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_sys_fan_led_status);
+
+ ret = g_drv->set_sys_fan_led_status(status);
+ return ret;
+}
+
+/* Similar to wb_get_sys_led_status */
+static ssize_t wb_get_sys_psu_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_sys_psu_led_status);
+
+ ret = g_drv->get_sys_psu_led_status(buf, count);
+ return ret;
+}
+
+/* Similar to wb_set_sys_led_status */
+static int wb_set_sys_psu_led_status(int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_sys_psu_led_status);
+
+ ret = g_drv->set_sys_psu_led_status(status);
+ return ret;
+}
+
+/* Similar to wb_get_sys_led_status */
+static ssize_t wb_get_id_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_id_led_status);
+
+ ret = g_drv->get_id_led_status(buf, count);
+ return ret;
+}
+
+/* Similar to wb_set_sys_led_status */
+static int wb_set_id_led_status(int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_id_led_status);
+
+ ret = g_drv->set_id_led_status(status);
+ return ret;
+}
+
+/**************************************end of sysled******************************************/
+
+static struct s3ip_sysfs_sysled_drivers_s drivers = {
+ /*
+ * set ODM sysled drivers to /sys/s3ip/sysled,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_sys_led_status = wb_get_sys_led_status,
+ .set_sys_led_status = wb_set_sys_led_status,
+ .get_bmc_led_status = wb_get_bmc_led_status,
+ .set_bmc_led_status = wb_set_bmc_led_status,
+ .get_sys_fan_led_status = wb_get_sys_fan_led_status,
+ .set_sys_fan_led_status = wb_set_sys_fan_led_status,
+ .get_sys_psu_led_status = wb_get_sys_psu_led_status,
+ .set_sys_psu_led_status = wb_set_sys_psu_led_status,
+ .get_id_led_status = wb_get_id_led_status,
+ .set_id_led_status = wb_set_id_led_status,
+};
+
+static int __init sysled_init(void)
+{
+ int ret;
+
+ SYSLED_INFO("sysled_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_sysled_drivers_register(&drivers);
+ if (ret < 0) {
+ SYSLED_ERR("sysled drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+
+ SYSLED_INFO("sysled create success.\n");
+ return 0;
+}
+
+static void __exit sysled_exit(void)
+{
+ s3ip_sysfs_sysled_drivers_unregister();
+ SYSLED_INFO("sysled_exit ok.\n");
+ return;
+}
+
+module_init(sysled_init);
+module_exit(sysled_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("sysled device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/system_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/system_device_driver.c
new file mode 100644
index 000000000000..65013163cb90
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/system_device_driver.c
@@ -0,0 +1,109 @@
+/*
+ * An system_device_driver driver for system devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include
+
+#include "device_driver_common.h"
+#include "system_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define TEMP_SENSOR_INFO(fmt, args...) LOG_INFO("system: ", fmt, ##args)
+#define TEMP_SENSOR_ERR(fmt, args...) LOG_ERR("system: ", fmt, ##args)
+#define TEMP_SENSOR_DBG(fmt, args...) LOG_DBG("system: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+static ssize_t wb_set_system_value(unsigned int type, int value)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_system_value);
+
+ ret = g_drv->set_system_value(type, value);
+ return ret;
+}
+
+static ssize_t wb_get_system_value(unsigned int type, int *value, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_system_value);
+
+ ret = g_drv->get_system_value(type, value, buf, count);
+ return ret;
+}
+
+static ssize_t wb_get_system_port_power_status(unsigned int type, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_system_port_power_status);
+
+ ret = g_drv->get_system_port_power_status(type, buf, count);
+ return ret;
+}
+/***********************************end of main board temp*************************************/
+
+static struct s3ip_sysfs_system_drivers_s drivers = {
+ /*
+ * set ODM system drivers to /sys/s3ip/system,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_system_value = wb_get_system_value,
+ .set_system_value = wb_set_system_value,
+ .get_system_port_power_status = wb_get_system_port_power_status,
+};
+
+static int __init system_dev_drv_init(void)
+{
+ int ret;
+
+ TEMP_SENSOR_INFO("system_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_system_drivers_register(&drivers);
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("temp sensor drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ TEMP_SENSOR_INFO("system_init success.\n");
+ return 0;
+}
+
+static void __exit system_dev_drv_exit(void)
+{
+ s3ip_sysfs_system_drivers_unregister();
+ TEMP_SENSOR_INFO("system_exit success.\n");
+ return;
+}
+
+module_init(system_dev_drv_init);
+module_exit(system_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("system device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/temp_sensor_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/temp_sensor_device_driver.c
new file mode 100644
index 000000000000..afd0bc25c8d0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/temp_sensor_device_driver.c
@@ -0,0 +1,275 @@
+/*
+ * An temp_sensor_device_driver driver for temperature devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include
+
+#include "device_driver_common.h"
+#include "temp_sensor_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define TEMP_SENSOR_INFO(fmt, args...) LOG_INFO("temp_sensor: ", fmt, ##args)
+#define TEMP_SENSOR_ERR(fmt, args...) LOG_ERR("temp_sensor: ", fmt, ##args)
+#define TEMP_SENSOR_DBG(fmt, args...) LOG_DBG("temp_sensor: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/***************************************main board temp*****************************************/
+/*
+ * wb_get_main_board_temp_number - Used to get main board temperature sensors number,
+ *
+ * This function returns main board temperature sensors by your switch,
+ * If there is no main board temperature sensors, returns 0,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_get_main_board_temp_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_number);
+
+ ret = g_drv->get_main_board_temp_number();
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_alias - Used to identify the location of the temperature sensor,
+ * such as air_inlet, air_outlet and so on.
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_alias(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_alias);
+
+ ret = g_drv->get_main_board_temp_alias(temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_type - Used to get the model of temperature sensor,
+ * such as lm75, tmp411 and so on
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_type(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_type);
+
+ ret = g_drv->get_main_board_temp_type(temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_max - Used to get the maximum threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_max(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_max);
+
+ ret = g_drv->get_main_board_temp_max(temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_min - Used to get the minimum threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_min(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_min);
+
+ ret = g_drv->get_main_board_temp_min(temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_high - Used to get the highimum threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_high(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_high);
+
+ ret = g_drv->get_main_board_temp_high(temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_low - Used to get the lowimum threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_low(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_low);
+
+ ret = g_drv->get_main_board_temp_low(temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_value - Used to get the input value of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_value(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_value);
+
+ ret = g_drv->get_main_board_temp_value(temp_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_temp_monitor_flag - Used to get the monitor flag of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_temp_monitor_flag(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_temp_monitor_flag);
+
+ ret = g_drv->get_main_board_temp_monitor_flag(temp_index, buf, count);
+ return ret;
+}
+/***********************************end of main board temp*************************************/
+
+static struct s3ip_sysfs_temp_sensor_drivers_s drivers = {
+ /*
+ * set ODM temperature sensor drivers to /sys/s3ip/temp_sensor,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_main_board_temp_number = wb_get_main_board_temp_number,
+ .get_main_board_temp_alias = wb_get_main_board_temp_alias,
+ .get_main_board_temp_type = wb_get_main_board_temp_type,
+ .get_main_board_temp_max = wb_get_main_board_temp_max,
+ .get_main_board_temp_min = wb_get_main_board_temp_min,
+ .get_main_board_temp_value = wb_get_main_board_temp_value,
+ .get_main_board_temp_high = wb_get_main_board_temp_high,
+ .get_main_board_temp_low = wb_get_main_board_temp_low,
+ .get_main_board_temp_monitor_flag = wb_get_main_board_temp_monitor_flag,
+};
+
+static int __init temp_sensor_dev_drv_init(void)
+{
+ int ret;
+
+ TEMP_SENSOR_INFO("temp_sensor_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_temp_sensor_drivers_register(&drivers);
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("temp sensor drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ TEMP_SENSOR_INFO("temp_sensor_init success.\n");
+ return 0;
+}
+
+static void __exit temp_sensor_dev_drv_exit(void)
+{
+ s3ip_sysfs_temp_sensor_drivers_unregister();
+ TEMP_SENSOR_INFO("temp_sensor_exit success.\n");
+ return;
+}
+
+module_init(temp_sensor_dev_drv_init);
+module_exit(temp_sensor_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("temperature sensors device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/transceiver_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/transceiver_device_driver.c
new file mode 100644
index 000000000000..1aad05fea3f5
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/transceiver_device_driver.c
@@ -0,0 +1,481 @@
+/*
+ * An transceiver_device_driver driver for sff devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "device_driver_common.h"
+#include "transceiver_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define SFF_INFO(fmt, args...) LOG_INFO("sff: ", fmt, ##args)
+#define SFF_ERR(fmt, args...) LOG_ERR("sff: ", fmt, ##args)
+#define SFF_DBG(fmt, args...) LOG_DBG("sff: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/****************************************transceiver******************************************/
+static int wb_get_eth_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_number);
+
+ ret = g_drv->get_eth_number();
+ return ret;
+}
+
+/*
+ * wb_get_transceiver_power_on_status - Used to get the whole machine port power on status,
+ * filled the value to buf, 0: power off, 1: power on
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_transceiver_power_on_status(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_transceiver_power_on_status);
+
+ ret = g_drv->get_transceiver_power_on_status(buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_transceiver_power_on_status - Used to set the whole machine port power on status,
+ * @status: power on status, 0: power off, 1: power on
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_transceiver_power_on_status(int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_transceiver_power_on_status);
+
+ ret = g_drv->set_transceiver_power_on_status(status);
+ return ret;
+}
+
+/*
+ * wb_get_transceiver_present_status - Used to get the whole machine port present status,
+ * filled the value to buf, 0: absent, 1: present
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_transceiver_present_status(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_transceiver_present_status);
+
+ ret = g_drv->get_transceiver_present_status(buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eth_power_on_status - Used to get single port power on status,
+ * filled the value to buf, 0: power off, 1: power on
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_power_on_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_power_on_status);
+
+ ret = g_drv->get_eth_power_on_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_eth_power_on_status - Used to set single port power on status,
+ * @eth_index: start with 1
+ * @status: power on status, 0: power off, 1: power on
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_eth_power_on_status(unsigned int eth_index, int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_eth_power_on_status);
+
+ ret = g_drv->set_eth_power_on_status(eth_index, status);
+ return ret;
+}
+
+/*
+ * wb_get_eth_tx_fault_status - Used to get port tx_fault status,
+ * filled the value to buf, 0: normal, 1: abnormal
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_tx_fault_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_tx_fault_status);
+
+ ret = g_drv->get_eth_tx_fault_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eth_tx_disable_status - Used to get port tx_disable status,
+ * filled the value to buf, 0: tx_enable, 1: tx_disable
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_tx_disable_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_tx_disable_status);
+
+ ret = g_drv->get_eth_tx_disable_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_eth_tx_disable_status - Used to set port tx_disable status,
+ * @eth_index: start with 1
+ * @status: tx_disable status, 0: tx_enable, 1: tx_disable
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_eth_tx_disable_status(unsigned int eth_index, int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_eth_tx_disable_status);
+
+ ret = g_drv->set_eth_tx_disable_status(eth_index, status);
+ return ret;
+}
+
+/*
+ * wb_get_eth_present_status - Used to get port present status,
+ * filled the value to buf, 1: present, 0: absent
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_present_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_present_status);
+
+ ret = g_drv->get_eth_present_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eth_rx_los_status - Used to get port rx_los status,
+ * filled the value to buf, 0: normal, 1: abnormal
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_rx_los_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_rx_los_status);
+
+ ret = g_drv->get_eth_rx_los_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eth_reset_status - Used to get port reset status,
+ * filled the value to buf, 0: unreset, 1: reset
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_reset_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_reset_status);
+
+ ret = g_drv->get_eth_reset_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_eth_reset_status - Used to set port reset status,
+ * @eth_index: start with 1
+ * @status: reset status, 0: unreset, 1: reset
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_eth_reset_status(unsigned int eth_index, int status)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_eth_reset_status);
+
+ ret = g_drv->set_eth_reset_status(eth_index, status);
+ return ret;
+}
+
+/*
+ * wb_get_eth_low_power_mode_status - Used to get port low power mode status,
+ * filled the value to buf, 0: high power mode, 1: low power mode
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_low_power_mode_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_low_power_mode_status);
+
+ ret = g_drv->get_eth_low_power_mode_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eth_interrupt_status - Used to get port interruption status,
+ * filled the value to buf, 0: no interruption, 1: interruption
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_eth_interrupt_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_interrupt_status);
+
+ ret = g_drv->get_eth_interrupt_status(eth_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_eth_eeprom_size - Used to get port eeprom size
+ *
+ * This function returns the size of port eeprom,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_get_eth_eeprom_size(unsigned int eth_index)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_eeprom_size);
+
+ ret = g_drv->get_eth_eeprom_size(eth_index);
+ return ret;
+}
+
+/*
+ * wb_read_eth_eeprom_data - Used to read port eeprom data,
+ * @buf: Data read buffer
+ * @offset: offset address to read port eeprom data
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_read_eth_eeprom_data(unsigned int eth_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->read_eth_eeprom_data);
+
+ ret = g_drv->read_eth_eeprom_data(eth_index, buf, offset, count);
+ return ret;
+}
+
+/*
+ * wb_write_eth_eeprom_data - Used to write port eeprom data
+ * @buf: Data write buffer
+ * @offset: offset address to write port eeprom data
+ * @count: length of buf
+ *
+ * This function returns the written length of port eeprom,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_write_eth_eeprom_data(unsigned int eth_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->write_eth_eeprom_data);
+
+ ret = g_drv->write_eth_eeprom_data(eth_index, buf, offset, count);
+ return ret;
+}
+
+static ssize_t wb_get_eth_optoe_type(unsigned int sff_index, int *optoe_type, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_eth_optoe_type);
+
+ ret = g_drv->get_eth_optoe_type(sff_index, optoe_type, buf, count);
+ return ret;
+}
+
+static ssize_t wb_set_eth_optoe_type(unsigned int sff_index, int optoe_type)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_eth_optoe_type);
+
+ ret = g_drv->set_eth_optoe_type(sff_index, optoe_type);
+ return ret;
+}
+
+/************************************end of transceiver***************************************/
+
+static struct s3ip_sysfs_transceiver_drivers_s drivers = {
+ /*
+ * set ODM transceiver drivers to /sys/s3ip/transceiver,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_eth_number = wb_get_eth_number,
+ .get_transceiver_power_on_status = wb_get_transceiver_power_on_status,
+ .set_transceiver_power_on_status = wb_set_transceiver_power_on_status,
+ .get_transceiver_present_status = wb_get_transceiver_present_status,
+ .get_eth_power_on_status = wb_get_eth_power_on_status,
+ .set_eth_power_on_status = wb_set_eth_power_on_status,
+ .get_eth_tx_fault_status = wb_get_eth_tx_fault_status,
+ .get_eth_tx_disable_status = wb_get_eth_tx_disable_status,
+ .set_eth_tx_disable_status = wb_set_eth_tx_disable_status,
+ .get_eth_present_status = wb_get_eth_present_status,
+ .get_eth_rx_los_status = wb_get_eth_rx_los_status,
+ .get_eth_reset_status = wb_get_eth_reset_status,
+ .set_eth_reset_status = wb_set_eth_reset_status,
+ .get_eth_low_power_mode_status = wb_get_eth_low_power_mode_status,
+ .get_eth_interrupt_status = wb_get_eth_interrupt_status,
+ .get_eth_eeprom_size = wb_get_eth_eeprom_size,
+ .read_eth_eeprom_data = wb_read_eth_eeprom_data,
+ .write_eth_eeprom_data = wb_write_eth_eeprom_data,
+ .get_eth_optoe_type = wb_get_eth_optoe_type,
+ .set_eth_optoe_type = wb_set_eth_optoe_type,
+};
+
+static int __init sff_dev_drv_init(void)
+{
+ int ret;
+
+ SFF_INFO("sff_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_sff_drivers_register(&drivers);
+ if (ret < 0) {
+ SFF_ERR("transceiver drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ SFF_INFO("sff_init success.\n");
+ return 0;
+}
+
+static void __exit sff_dev_drv_exit(void)
+{
+ s3ip_sysfs_sff_drivers_unregister();
+ SFF_INFO("sff_exit success.\n");
+ return;
+}
+
+module_init(sff_dev_drv_init);
+module_exit(sff_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("transceiver device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/vol_sensor_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/vol_sensor_device_driver.c
new file mode 100644
index 000000000000..a2fc96551235
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/vol_sensor_device_driver.c
@@ -0,0 +1,267 @@
+/*
+ * An vol_sensor_device_driver driver for voltage devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include
+
+#include "device_driver_common.h"
+#include "vol_sensor_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define VOL_SENSOR_INFO(fmt, args...) LOG_INFO("vol_sensor: ", fmt, ##args)
+#define VOL_SENSOR_ERR(fmt, args...) LOG_ERR("vol_sensor: ", fmt, ##args)
+#define VOL_SENSOR_DBG(fmt, args...) LOG_DBG("vol_sensor: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/*************************************main board voltage***************************************/
+static int wb_get_main_board_vol_number(void)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_number);
+
+ ret = g_drv->get_main_board_vol_number();
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_alias - Used to identify the location of the voltage sensor,
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_alias(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_alias);
+
+ ret = g_drv->get_main_board_vol_alias(vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_type - Used to get the model of voltage sensor,
+ * such as udc90160, tps53622 and so on
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_type(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_type);
+
+ ret = g_drv->get_main_board_vol_type(vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_max - Used to get the maximum threshold of voltage sensor
+ * filled the value to buf, the value is integer with mV
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_max(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_max);
+
+ ret = g_drv->get_main_board_vol_max(vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_min - Used to get the minimum threshold of voltage sensor
+ * filled the value to buf, the value is integer with mV
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_min(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_min);
+
+ ret = g_drv->get_main_board_vol_min(vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_range - Used to get the output error value of voltage sensor
+ * filled the value to buf
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_range(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_range);
+
+ ret = g_drv->get_main_board_vol_range(vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_nominal_value - Used to get the nominal value of voltage sensor
+ * filled the value to buf
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_nominal_value(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_nominal_value);
+
+ ret = g_drv->get_main_board_vol_nominal_value(vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_value - Used to get the input value of voltage sensor
+ * filled the value to buf, the value is integer with mV
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_value(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_value);
+
+ ret = g_drv->get_main_board_vol_value(vol_index, buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_main_board_vol_monitor_flag - Used to get the monitor flag of voltage sensor
+ * filled the value to buf, the value is integer with mV
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_main_board_vol_monitor_flag(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_main_board_vol_monitor_flag);
+
+ ret = g_drv->get_main_board_vol_monitor_flag(vol_index, buf, count);
+ return ret;
+}
+/*********************************end of main board voltage************************************/
+
+static struct s3ip_sysfs_vol_sensor_drivers_s drivers = {
+ /*
+ * set ODM voltage sensor drivers to /sys/s3ip/vol_sensor,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_main_board_vol_number = wb_get_main_board_vol_number,
+ .get_main_board_vol_alias = wb_get_main_board_vol_alias,
+ .get_main_board_vol_type = wb_get_main_board_vol_type,
+ .get_main_board_vol_max = wb_get_main_board_vol_max,
+ .get_main_board_vol_min = wb_get_main_board_vol_min,
+ .get_main_board_vol_range = wb_get_main_board_vol_range,
+ .get_main_board_vol_nominal_value = wb_get_main_board_vol_nominal_value,
+ .get_main_board_vol_value = wb_get_main_board_vol_value,
+ .get_main_board_vol_monitor_flag = wb_get_main_board_vol_monitor_flag,
+};
+
+static int __init vol_sensor_dev_drv_init(void)
+{
+ int ret;
+
+ VOL_SENSOR_INFO("vol_sensor_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_vol_sensor_drivers_register(&drivers);
+ if (ret < 0) {
+ VOL_SENSOR_ERR("vol sensor drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ VOL_SENSOR_INFO("vol_sensor_init success.\n");
+ return 0;
+}
+
+static void __exit vol_sensor_dev_drv_exit(void)
+{
+ s3ip_sysfs_vol_sensor_drivers_unregister();
+ VOL_SENSOR_INFO("vol_sensor_exit success.\n");
+ return;
+}
+
+module_init(vol_sensor_dev_drv_init);
+module_exit(vol_sensor_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("voltage sensors device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/watchdog_device_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/watchdog_device_driver.c
new file mode 100644
index 000000000000..b2075afe1081
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/device_driver/watchdog_device_driver.c
@@ -0,0 +1,214 @@
+/*
+ * An watchdog_device_driver driver for watchdog devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "device_driver_common.h"
+#include "watchdog_sysfs.h"
+#include "dfd_sysfs_common.h"
+
+#define WDT_INFO(fmt, args...) LOG_INFO("watchdog: ", fmt, ##args)
+#define WDT_ERR(fmt, args...) LOG_ERR("watchdog: ", fmt, ##args)
+#define WDT_DBG(fmt, args...) LOG_DBG("watchdog: ", fmt, ##args)
+
+static int g_loglevel = 0;
+static struct switch_drivers_s *g_drv = NULL;
+
+/****************************************watchdog*********************************************/
+/*
+ * wb_get_watchdog_identify - Used to get watchdog identify, such as iTCO_wdt
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_watchdog_identify(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_watchdog_identify);
+
+ ret = g_drv->get_watchdog_identify(buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_watchdog_timeleft - Used to get watchdog timeleft,
+ * filled the value to buf
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_watchdog_timeleft(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_watchdog_timeleft);
+
+ ret = g_drv->get_watchdog_timeleft(buf, count);
+ return ret;
+}
+
+/*
+ * wb_get_watchdog_timeout - Used to get watchdog timeout,
+ * filled the value to buf
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_watchdog_timeout(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_watchdog_timeout);
+
+ ret = g_drv->get_watchdog_timeout(buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_watchdog_timeout - Used to set watchdog timeout,
+ * @value: timeout value
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_watchdog_timeout(int value)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_watchdog_timeout);
+
+ ret = g_drv->set_watchdog_timeout(value);
+ return ret;
+}
+
+/*
+ * wb_get_watchdog_enable_status - Used to get watchdog enable status,
+ * filled the value to buf, 0: disable, 1: enable
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t wb_get_watchdog_enable_status(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ check_p(g_drv);
+ check_p(g_drv->get_watchdog_enable_status);
+
+ ret = g_drv->get_watchdog_enable_status(buf, count);
+ return ret;
+}
+
+/*
+ * wb_set_watchdog_enable_status - Used to set watchdog enable status,
+ * @value: enable status value, 0: disable, 1: enable
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_watchdog_enable_status(int value)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_watchdog_enable_status);
+
+ ret = g_drv->set_watchdog_enable_status(value);
+ return ret;
+}
+
+/*
+ * wb_set_watchdog_reset - Used to feed watchdog,
+ * @value: any value to feed watchdog
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int wb_set_watchdog_reset(int value)
+{
+ int ret;
+
+ check_p(g_drv);
+ check_p(g_drv->set_watchdog_reset);
+
+ ret = g_drv->set_watchdog_reset(value);
+ return ret;
+}
+
+/*************************************end of watchdog*****************************************/
+
+static struct s3ip_sysfs_watchdog_drivers_s drivers = {
+ /*
+ * set ODM watchdog sensor drivers to /sys/s3ip/watchdog,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ .get_watchdog_identify = wb_get_watchdog_identify,
+ .get_watchdog_timeleft = wb_get_watchdog_timeleft,
+ .get_watchdog_timeout = wb_get_watchdog_timeout,
+ .set_watchdog_timeout = wb_set_watchdog_timeout,
+ .get_watchdog_enable_status = wb_get_watchdog_enable_status,
+ .set_watchdog_enable_status = wb_set_watchdog_enable_status,
+ .set_watchdog_reset = wb_set_watchdog_reset,
+};
+
+static int __init watchdog_dev_drv_init(void)
+{
+ int ret;
+
+ WDT_INFO("watchdog_init...\n");
+ g_drv = s3ip_switch_driver_get();
+ check_p(g_drv);
+
+ ret = s3ip_sysfs_watchdog_drivers_register(&drivers);
+ if (ret < 0) {
+ WDT_ERR("watchdog drivers register err, ret %d.\n", ret);
+ return ret;
+ }
+ WDT_INFO("watchdog create success.\n");
+ return 0;
+}
+
+static void __exit watchdog_dev_drv_exit(void)
+{
+ s3ip_sysfs_watchdog_drivers_unregister();
+ WDT_INFO("watchdog_exit success.\n");
+ return;
+}
+
+module_init(watchdog_dev_drv_init);
+module_exit(watchdog_dev_drv_exit);
+module_param(g_loglevel, int, 0644);
+MODULE_PARM_DESC(g_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4, all=0xf).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("watchdog device driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/Makefile
new file mode 100644
index 000000000000..98b0d0db75c4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/Makefile
@@ -0,0 +1,35 @@
+PWD = $(shell pwd)
+
+EXTRA_CFLAGS:= -I$(M)/include
+EXTRA_CFLAGS+= -Wall
+
+SUBDIR_CFG = cfg
+wb_switch_driver-objs := switch_driver.o wb_module.o \
+wb_fan_driver.o \
+wb_eeprom_driver.o \
+wb_cpld_driver.o \
+wb_fpga_driver.o \
+wb_led_driver.o \
+wb_slot_driver.o \
+wb_sensors_driver.o \
+wb_psu_driver.o \
+wb_sff_driver.o \
+wb_watchdog_driver.o \
+wb_system_driver.o \
+$(SUBDIR_CFG)/dfd_cfg.o \
+$(SUBDIR_CFG)/dfd_cfg_adapter.o \
+$(SUBDIR_CFG)/dfd_cfg_file.o \
+$(SUBDIR_CFG)/dfd_cfg_info.o \
+$(SUBDIR_CFG)/dfd_cfg_listnode.o \
+$(SUBDIR_CFG)/dfd_frueeprom.o \
+$(SUBDIR_CFG)/dfd_tlveeprom.o \
+
+obj-m := wb_switch_driver.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)/$(SUBDIR_CFG)/*.o $(PWD)/*.ko $(PWD)/*.mod.c $(PWD)/.*.cmd $(PWD)/$(SUBDIR_CFG)/.*.cmd
+ rm -f $(PWD)/Module.markers $(PWD)/Module.symvers $(PWD)/modules.order
+ rm -rf $(PWD)/.tmp_versions
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg.c
new file mode 100644
index 000000000000..0637d8566aa2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg.c
@@ -0,0 +1,1169 @@
+/*
+ * An dfd_cfg driver for cfg devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg_file.h"
+#include "dfd_cfg_listnode.h"
+#include "dfd_cfg_info.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg.h"
+
+/* Configuration item name */
+#ifdef DFD_CFG_ITEM
+#undef DFD_CFG_ITEM
+#endif
+#define DFD_CFG_ITEM(_id, _name, _index_min, _index_max) _name,
+static char *dfd_cfg_item_name[] = {
+ DFD_CFG_ITEM_ALL
+};
+
+/* The index range of the item is specified */
+#ifdef DFD_CFG_ITEM
+#undef DFD_CFG_ITEM
+#endif
+#define DFD_CFG_ITEM(_id, _name, _index_min, _index_max) {_index_min, _index_max},
+static index_range_t dfd_cfg_item_index_range[] = {
+ DFD_CFG_ITEM_ALL
+};
+
+/* led status register value conversion level list header */
+LIST_HEAD(dfd_lib_cfg_led_status_decode_conv_lst);
+
+/* Fan name Convert Air duct type chain head */
+LIST_HEAD(dfd_lib_cfg_fan_name_conv_dir_lst);
+
+/* Fan name Convert Air duct type chain head */
+LIST_HEAD(dfd_lib_cfg_power_name_conv_lst);
+
+/* Configure the root node of the necklace watch */
+static lnode_root_t dfd_ko_cfg_list_root;
+
+/* input key,and then get configuration string */
+char *key_to_name(uint64_t key)
+{
+ return dfd_cfg_item_name[key];
+}
+
+/* Strip out Spaces and carriage returns */
+void dfd_ko_cfg_del_space_lf_cr(char *str)
+{
+ int i, j;
+ int len;
+
+ if (str == NULL) {
+ DBG_DEBUG(DBG_ERROR, "param error, str is NULL\n");
+ return;
+ }
+ /* Remove all Spaces from the configuration line */
+ len = strlen(str);
+ for (i = 0; i < len; i++) {
+ if (str[i] == '\r' || str[i] == '\n' || str[i] == ' ') {
+ for (j = i; j < len - 1; j++) {
+ str[j] = str[j + 1];
+ }
+ str[j] = '\0';
+ len--;
+ i--;
+ }
+ }
+}
+
+void dfd_ko_cfg_del_lf_cr(char *str)
+{
+ int i, len;
+
+ len = strlen(str);
+ for (i = 0; i < len; i++) {
+ if (str[i] == '\r' || str[i] == '\n') {
+ str[i] = '\0';
+ }
+ }
+}
+
+/**
+ * Free linked list
+ * @root: Root node pointer
+ *
+ * @return : void
+ */
+void val_convert_node_lst_free(struct list_head *root)
+{
+ val_convert_node_t *node, *node_next;
+
+ if (root == NULL) {
+ return;
+ }
+
+ /* Iterate to delete the linked list */
+ list_for_each_entry_safe(node, node_next, root, lst) {
+ list_del(&node->lst);
+ kfree(node);
+ node = NULL;
+ }
+
+ return;
+
+}
+
+/* Register value conversion node added */
+static void dfd_ko_cfg_regval_conv_lst_add(struct list_head *root, int val, char *str,
+ int index1, int index2)
+{
+ val_convert_node_t *val_convert;
+
+ val_convert = (val_convert_node_t *)kmalloc(sizeof(val_convert_node_t), GFP_KERNEL);
+ if (val_convert == NULL) {
+ DBG_DEBUG(DBG_ERROR, "kmalloc val_convert_node_t fail\n");
+ return;
+ }
+ mem_clear(val_convert, sizeof(val_convert_node_t));
+
+ val_convert->int_val = val;
+ val_convert->index1 = index1;
+ val_convert->index2 = index2;
+ if (str != NULL) {
+ strlcpy(val_convert->str_val, str, sizeof(val_convert->str_val));
+ }
+
+ /* After initialization, the list does not change and does not need to be locked */
+ list_add_tail(&(val_convert->lst), root);
+}
+
+/* Get an index value from an integer value */
+static int dfd_ko_cfg_get_index2_by_intval(struct list_head *root, int val, int index1,
+ int *index2)
+{
+ val_convert_node_t *val_convert;
+
+ /* The list does not change after initialization and does not need to be locked */
+ list_for_each_entry(val_convert, root, lst) {
+ if ((val_convert->int_val == val) && (index1 == val_convert->index1)) {
+ *index2 = val_convert->index2;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* Gets an index value from a string value */
+static int dfd_ko_cfg_get_index_by_strval(struct list_head *root, char *str, int *index1, int *index2)
+{
+ val_convert_node_t *val_convert;
+
+ /* The list does not change after initialization and does not need to be locked */
+ list_for_each_entry(val_convert, root, lst) {
+ if (strncmp(val_convert->str_val, str, strlen(val_convert->str_val)) == 0) {
+ *index1 = val_convert->index1;
+ *index2 = val_convert->index2;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* Create a message lookup table */
+static void dfd_ko_cfg_convert_list_build(dfd_cfg_item_id_t cfg_item_id, int val, char *str,
+ int index1, int index2)
+{
+ if (cfg_item_id == DFD_CFG_ITEM_LED_STATUS_DECODE) {
+ dfd_ko_cfg_regval_conv_lst_add(&dfd_lib_cfg_led_status_decode_conv_lst, val, str, index1, index2);
+ } else if (cfg_item_id == DFD_CFG_ITEM_FAN_NAME) {
+ dfd_ko_cfg_regval_conv_lst_add(&dfd_lib_cfg_fan_name_conv_dir_lst, val, str, index1, index2);
+ } else if (cfg_item_id == DFD_CFG_ITEM_POWER_NAME) {
+ dfd_ko_cfg_regval_conv_lst_add(&dfd_lib_cfg_power_name_conv_lst, val, str, index1, index2);
+ }
+ return;
+}
+
+/**
+ * dfd_ko_cfg_get_led_status_decode2_by_regval - Reverse check the register value of the led status
+ * @regval: Defined led values
+ * @index1: led type
+ * @*value: Gets the register value of the led status
+ * @returns: 0 Succeeded, otherwise failed
+ */
+int dfd_ko_cfg_get_led_status_decode2_by_regval(int regval, int index1, int *value)
+{
+ int rv;
+
+ if (value == NULL) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ rv = dfd_ko_cfg_get_index2_by_intval(&dfd_lib_cfg_led_status_decode_conv_lst, regval,
+ index1, value);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get led status decode by regval[0x%x] index1[%d] fail\n",
+ regval, index1);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ return 0;
+}
+
+/**
+ * dfd_ko_cfg_get_fan_direction_by_name - obtain the air duct type by fan name
+ * @fan_name: Fan name
+ * @fan_direction: Duct type
+ *
+ * @returns: 0 Succeeded, otherwise failed
+ */
+int dfd_ko_cfg_get_fan_direction_by_name(char *fan_name, int *fan_direction)
+{
+ int rv;
+ int index1, index2;
+
+ if ((fan_name == NULL) || (fan_direction == NULL)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ rv = dfd_ko_cfg_get_index_by_strval(&dfd_lib_cfg_fan_name_conv_dir_lst, fan_name, &index1, &index2);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get fan direction by name[%s] fail\n", fan_name);
+ return -DFD_RV_NODE_FAIL;
+ }
+
+ *fan_direction = index1;
+
+ return 0;
+}
+
+/**
+ * dfd_ko_cfg_get_fan_direction_by_name - obtain the fan type by fan name
+ * @fan_name: Fan name
+ * @fan_type: Fan type
+ * @sub_type: Fan sub-type
+ *
+ * @returns: 0 Succeeded, otherwise failed
+ */
+int dfd_ko_cfg_get_fan_type_by_name(char *fan_name, int *fan_type, int *sub_type)
+{
+ int rv;
+ int index1, index2;
+
+ if ((fan_name == NULL) || (fan_type == NULL)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ rv = dfd_ko_cfg_get_index_by_strval(&dfd_lib_cfg_fan_name_conv_dir_lst, fan_name, &index1, &index2);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get fan direction by name[%s] fail\n", fan_name);
+ return -DFD_RV_NODE_FAIL;
+ }
+
+ *fan_type = index1;
+ *sub_type = index2;
+
+ return 0;
+}
+
+/**
+ * dfd_ko_cfg_get_power_type_by_name - obtain the power supply type by power supply name
+ * @name: PSU name
+ * @power_type: PSU type
+ *
+ * @returns: 0 Succeeded, otherwise failed
+ */
+int dfd_ko_cfg_get_power_type_by_name(char *power_name, int *power_type)
+{
+ int rv;
+ int index1, index2;
+
+ if ((power_name == NULL) || (power_type == NULL)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error\n");
+ return -1;
+ }
+
+ rv = dfd_ko_cfg_get_index_by_strval(&dfd_lib_cfg_power_name_conv_lst, power_name, &index1, &index2);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get power type by name[%s] fail\n", power_name);
+ return -1;
+ }
+
+ *power_type = index1;
+
+ return 0;
+}
+
+/* Convert a string to a value */
+static int dfd_ko_cfg_get_value_from_char(char *value_str, int32_t *value, int line_num)
+{
+ int value_tmp = 0;
+
+ if (strlen(value_str) == 0) {
+ DBG_DEBUG(DBG_WARN, "line%d: value str is empty\n", line_num);
+ *value = DFD_CFG_EMPTY_VALUE;
+ return 0;
+ }
+
+ /* Format processing data */
+ if ((strlen(value_str) > 2) && (value_str[0] == '0')
+ && (value_str[1] == 'x' || value_str[1] == 'X')) {
+ value_tmp = (int32_t)simple_strtol(value_str, NULL, 16); /* hexadecimal */
+ } else {
+ value_tmp = (int32_t)simple_strtol(value_str, NULL, 10); /* decimalism */
+ }
+
+ *value = value_tmp;
+ return 0;
+}
+
+/* Get an index value,index2=NULL indicates that there is only one level index */
+static int dfd_ko_cfg_analyse_index(char *index_str, int *index1, int *index2, int line_num)
+{
+ int rv;
+ char *index1_begin_char, *index2_begin_char;
+
+ /* first character should be'_' */
+ if (index_str[0] != '_') {
+ DBG_DEBUG(DBG_ERROR, "line%d: no '-' between name and index1\n", line_num);
+ return -1;
+ }
+
+ /* Gets the first-level index value */
+ index1_begin_char = index_str;
+ rv = dfd_ko_cfg_get_value_from_char(++index1_begin_char, index1, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* No secondary index exists */
+ if (index2 == NULL) {
+ return 0;
+ }
+
+ /* Gets the secondary index value */
+ index2_begin_char = strchr(index1_begin_char, '_');
+ if (index2_begin_char == NULL) {
+ DBG_DEBUG(DBG_ERROR, "line%d: no '-' between index1 and index2\n", line_num);
+ return -1;
+ } else {
+ rv = dfd_ko_cfg_get_value_from_char(++index2_begin_char, index2, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* The index value of the array is checked. index2=NULL indicates that it is not checked */
+static int dfd_ko_cfg_check_array_index(index_range_t *index_range, int *index1, int *index2,
+ int line_num)
+{
+ /* Level 1 index value check */
+ if ((*index1 < 0) || (*index1 > index_range->index1_max)) {
+ DBG_DEBUG(DBG_ERROR, "line%d: index1[%d] invalid, max=%d\n", line_num, *index1,
+ index_range->index1_max);
+ return -1;
+ }
+
+ /* The secondary index does not exist */
+ if (index2 == NULL) {
+ return 0;
+ }
+
+ /* Secondary index value check */
+ if ((*index2 < 0) || (*index2 > index_range->index2_max)) {
+ DBG_DEBUG(DBG_ERROR, "line%d: index2[%d] invalid, max=%d\n", line_num, *index2,
+ index_range->index2_max);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Get index value */
+static int dfd_ko_cfg_get_index(char *index_str, index_range_t *index_range, int *index1,
+ int *index2, int line_num)
+{
+ int rv;
+
+ /* No secondary index value exists */
+ if (index_range->index2_max == INDEX_NOT_EXIST) {
+ index2 = NULL;
+ }
+
+ /* Analytic index value */
+ rv = dfd_ko_cfg_analyse_index(index_str, index1, index2, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* Check the index value for valid values */
+ rv = dfd_ko_cfg_check_array_index(index_range, index1, index2, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Add a configuration item */
+static int dfd_ko_cfg_add_int_item(uint64_t key, int value, int line_num)
+{
+ int rv;
+ int *int_cfg;
+
+ int_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key);
+ if (int_cfg == NULL) {
+ /* Node does not exist,kmalloc new node */
+ int_cfg = (int *)kmalloc(sizeof(int), GFP_KERNEL);
+ if (int_cfg == NULL) {
+ DBG_DEBUG(DBG_ERROR, "line%d: kmalloc int fail\n", line_num);
+ return -1;
+ }
+
+ /* Add to linked list */
+ *int_cfg = value;
+ rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, int_cfg);
+ if (rv == 0) {
+ DBG_DEBUG(DBG_VERBOSE, "line%d: add int item[%d] success, key=0x%08llx\n",
+ line_num, value, key);
+ } else {
+ kfree(int_cfg);
+ int_cfg = NULL;
+ DBG_DEBUG(DBG_ERROR, "line%d: add int item[%d] fail, key=0x%08llx rv=%d \n",
+ line_num, value, key, rv);
+ return -1;
+ }
+ } else {
+ /* If the node already exists, modify the configuration value */
+ DBG_DEBUG(DBG_WARN, "line%d: replace int item[%d->%d], key=0x%08llx\n",
+ line_num, *int_cfg, value, key);
+ *int_cfg = value;
+ }
+
+ return 0;
+}
+
+/* Parse int type configuration */
+static int dfd_ko_cfg_analyse_int_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name,
+ char *arg_value, char *cfg_pre, index_range_t *index_range, int line_num)
+{
+ int rv;
+ int index1 = 0, index2 = 0;
+ int value, key;
+ char *arg_name_tmp;
+
+ /* Get index value */
+ if (index_range->index1_max != INDEX_NOT_EXIST) {
+ arg_name_tmp = arg_name + strlen(cfg_pre);
+ rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+ }
+
+ /* Get configuration value */
+ rv = dfd_ko_cfg_get_value_from_char(arg_value, &value, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* Add a configuration item */
+ key = DFD_CFG_KEY(cfg_item_id, index1, index2);
+ rv = dfd_ko_cfg_add_int_item(key, value, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* Some data needs to be backtracked, and an int type backtracked linked list is created */
+ dfd_ko_cfg_convert_list_build(cfg_item_id, value, NULL, index1, index2);
+ return 0;
+}
+
+/* Add a configuration item */
+static int dfd_ko_cfg_add_str_item(uint64_t key, char *str, int line_num)
+{
+ int rv;
+ char *str_cfg;
+
+ str_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key);
+ if (str_cfg == NULL) {
+ /* kmalloc new node */
+ str_cfg = (char *)kmalloc(DFD_CFG_STR_MAX_LEN, GFP_KERNEL);
+ if (str_cfg == NULL) {
+ DBG_DEBUG(DBG_ERROR, "line%d: kmalloc str[%lu] fail\n", line_num, strlen(str));
+ return -1;
+ }
+ mem_clear(str_cfg, DFD_CFG_STR_MAX_LEN);
+ strlcpy(str_cfg, str, DFD_CFG_STR_MAX_LEN);
+
+ /* Add to linked list */
+ rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, str_cfg);
+ if (rv == 0) {
+ DBG_DEBUG(DBG_VERBOSE, "line%d: add string item[%s] success, key=0x%08llx\n",
+ line_num, str_cfg, key);
+ } else {
+ kfree(str_cfg);
+ str_cfg = NULL;
+ DBG_DEBUG(DBG_ERROR, "line%d: add string item[%s] fail, key=0x%08llx rv=%d \n",
+ line_num, str_cfg, key, rv);
+ return -1;
+ }
+ } else {
+ DBG_DEBUG(DBG_WARN, "line%d: replace string item[%s->%s], key=0x%08llx\n",
+ line_num, str_cfg, str, key);
+ mem_clear(str_cfg, DFD_CFG_STR_MAX_LEN);
+ strlcpy(str_cfg, str, DFD_CFG_STR_MAX_LEN);
+ }
+
+ return 0;
+}
+
+/* Parse the str type configuration */
+static int dfd_ko_cfg_analyse_str_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name,
+ char *arg_value, char *cfg_pre, index_range_t *index_range, int line_num)
+{
+ int rv;
+ int index1 = 0, index2 = 0;
+ int btree_key;
+ char *arg_name_tmp;
+
+ /* Get index value */
+ if (index_range->index1_max != INDEX_NOT_EXIST) {
+ arg_name_tmp = arg_name + strlen(cfg_pre);
+ rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+ }
+
+ /* Length check */
+ if (strlen(arg_value) >= DFD_CFG_STR_MAX_LEN) {
+ DBG_DEBUG(DBG_ERROR, "line%d: string item[%s] is too long \n", line_num, arg_value);
+ return -1;
+ }
+
+ /* Add a configuration item */
+ btree_key = DFD_CFG_KEY(cfg_item_id, index1, index2);
+ rv = dfd_ko_cfg_add_str_item(btree_key, arg_value, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* Part of the data need to reverse lookup, create a string type reverse lookup list */
+ dfd_ko_cfg_convert_list_build(cfg_item_id, 0, arg_value, index1, index2);
+ return 0;
+}
+
+/* Gets the dfd_i2c_dev_t member */
+static int dfd_ko_cfg_get_i2c_dev_member(char *member_str, dfd_i2c_dev_mem_t *member, int line_num)
+{
+ dfd_i2c_dev_mem_t mem_index;
+
+ for (mem_index = DFD_I2C_DEV_MEM_BUS; mem_index < DFD_I2C_DEV_MEM_END; mem_index++) {
+ if (memcmp(member_str, g_dfd_i2c_dev_mem_str[mem_index],
+ strlen(g_dfd_i2c_dev_mem_str[mem_index])) == 0) {
+ *member = mem_index;
+ return 0;
+ }
+ }
+
+ DBG_DEBUG(DBG_ERROR, "line%d: i2c dev member[%s] invalid\n", line_num, member_str);
+ return -1;
+}
+
+/* Set the i2c_dev member value */
+static void dfd_ko_cfg_set_i2c_dev_mem_value(dfd_i2c_dev_t *i2c_dev, dfd_i2c_dev_mem_t member,
+ int value)
+{
+ switch (member) {
+ case DFD_I2C_DEV_MEM_BUS:
+ i2c_dev->bus = value;
+ break;
+ case DFD_I2C_DEV_MEM_ADDR:
+ i2c_dev->addr = value;
+ break;
+ default:
+ break;
+ }
+}
+
+/* Add a configuration item */
+static int dfd_ko_cfg_add_i2c_dev_item(uint64_t key, dfd_i2c_dev_mem_t member, int value, int line_num)
+{
+ int rv;
+ dfd_i2c_dev_t *i2c_dev_cfg;
+
+ i2c_dev_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key);
+ if (i2c_dev_cfg == NULL) {
+ /* Node does not exist,kmalloc new node */
+ i2c_dev_cfg = (dfd_i2c_dev_t *)kmalloc(sizeof(dfd_i2c_dev_t), GFP_KERNEL);
+ if (i2c_dev_cfg == NULL) {
+ DBG_DEBUG(DBG_ERROR, "line%d: kmalloc i2c_dev fail\n", line_num);
+ return -1;
+ }
+ mem_clear(i2c_dev_cfg, sizeof(dfd_i2c_dev_t));
+
+ /* Add to linked list */
+ dfd_ko_cfg_set_i2c_dev_mem_value(i2c_dev_cfg, member, value);
+ rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, i2c_dev_cfg);
+ if (rv == 0) {
+ DBG_DEBUG(DBG_VERBOSE, "line%d: add i2c_dev item[%s=%d] success, key=0x%08llx\n",
+ line_num, g_dfd_i2c_dev_mem_str[member], value, key);
+ } else {
+ kfree(i2c_dev_cfg);
+ i2c_dev_cfg = NULL;
+ DBG_DEBUG(DBG_ERROR, "line%d: add i2c_dev item[%s=%d] fail, key=0x%08llx rv=%d\n",
+ line_num, g_dfd_i2c_dev_mem_str[member], value, key, rv);
+ return -1;
+ }
+ } else {
+ /* If the node already exists, modify the configuration value */
+ DBG_DEBUG(DBG_VERBOSE, "line%d: replace i2c_dev item[%s=%d], key=0x%08llx\n", line_num,
+ g_dfd_i2c_dev_mem_str[member], value, key);
+ dfd_ko_cfg_set_i2c_dev_mem_value(i2c_dev_cfg, member, value);
+ }
+
+ return 0;
+}
+
+/* Parse the dfd_i2c_dev_t type configuration */
+static int dfd_ko_cfg_analyse_i2c_dev_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name,
+ char *arg_value, char *cfg_pre, index_range_t *index_range, int line_num)
+{
+ int rv;
+ int index1 = 0, index2 = 0;
+ int value, key;
+ char *arg_name_tmp;
+ dfd_i2c_dev_mem_t member;
+
+ /* Parsing structure member */
+ arg_name_tmp = arg_name + strlen(cfg_pre);
+ rv = dfd_ko_cfg_get_i2c_dev_member(arg_name_tmp, &member, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* Get index value */
+ if (index_range->index1_max != INDEX_NOT_EXIST) {
+ arg_name_tmp += strlen(g_dfd_i2c_dev_mem_str[member]);
+ rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+ }
+
+ /* Value acquisition */
+ rv = dfd_ko_cfg_get_value_from_char(arg_value, &value, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* Add a configuration item */
+ key = DFD_CFG_KEY(cfg_item_id, index1, index2);
+ rv = dfd_ko_cfg_add_i2c_dev_item(key, member, value, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* String to enumeration value */
+static int dfd_ko_cfg_get_enum_value_by_str(char *enum_val_str[], int enum_val_end, char *buf)
+{
+ int i;
+ int enum_val;
+
+ enum_val = DFD_CFG_INVALID_VALUE;
+ for (i = 0; i < enum_val_end; i++) {
+ if (memcmp(buf, enum_val_str[i], strlen(enum_val_str[i])) == 0) {
+ enum_val = i;
+ break;
+ }
+ }
+
+ return enum_val;
+}
+
+/* Obtain the info_ctrl_t member */
+static int dfd_ko_cfg_get_info_ctrl_member(char *member_str, info_ctrl_mem_t *member, int line_num)
+{
+ info_ctrl_mem_t mem_index;
+
+ for (mem_index = INFO_CTRL_MEM_MODE; mem_index < INFO_CTRL_MEM_END; mem_index++) {
+ if (memcmp(member_str, g_info_ctrl_mem_str[mem_index],
+ strlen(g_info_ctrl_mem_str[mem_index])) == 0) {
+ *member = mem_index;
+ return 0;
+ }
+ }
+
+ DBG_DEBUG(DBG_ERROR, "line%d: info ctrl member[%s] invalid\n", line_num, member_str);
+ return -1;
+}
+
+/* Set the info_ctrl member value */
+static void dfd_ko_cfg_set_info_ctrl_mem_value(info_ctrl_t *info_ctrl, info_ctrl_mem_t member,
+ char *buf_val, int line_num)
+{
+ switch (member) {
+ case INFO_CTRL_MEM_MODE:
+ info_ctrl->mode = dfd_ko_cfg_get_enum_value_by_str(g_info_ctrl_mode_str,
+ INFO_CTRL_MODE_END, buf_val);
+ break;
+ case INFO_CTRL_MEM_INT_CONS:
+ dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->int_cons), line_num);
+ break;
+ case INFO_CTRL_MEM_SRC:
+ info_ctrl->src = dfd_ko_cfg_get_enum_value_by_str(g_info_src_str, INFO_SRC_END, buf_val);
+ break;
+ case INFO_CTRL_MEM_FRMT:
+ info_ctrl->frmt = dfd_ko_cfg_get_enum_value_by_str(g_info_frmt_str, INFO_FRMT_END, buf_val);
+ break;
+ case INFO_CTRL_MEM_POLA:
+ info_ctrl->pola = dfd_ko_cfg_get_enum_value_by_str(g_info_pola_str, INFO_POLA_END, buf_val);
+ break;
+ case INFO_CTRL_MEM_FPATH:
+ mem_clear(info_ctrl->fpath, sizeof(info_ctrl->fpath));
+ strlcpy(info_ctrl->fpath, buf_val, sizeof(info_ctrl->fpath));
+ break;
+ case INFO_CTRL_MEM_ADDR:
+ dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->addr), line_num);
+ break;
+ case INFO_CTRL_MEM_LEN:
+ dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->len), line_num);
+ break;
+ case INFO_CTRL_MEM_BIT_OFFSET:
+ dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->bit_offset), line_num);
+ break;
+ case INFO_CTRL_MEM_STR_CONS:
+ mem_clear(info_ctrl->str_cons, sizeof(info_ctrl->str_cons));
+ strlcpy(info_ctrl->str_cons, buf_val, sizeof(info_ctrl->str_cons));
+ break;
+ case INFO_CTRL_MEM_INT_EXTRA1:
+ dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->int_extra1), line_num);
+ break;
+ case INFO_CTRL_MEM_INT_EXTRA2:
+ dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->int_extra2), line_num);
+ break;
+ case INFO_CTRL_MEM_INT_EXTRA3:
+ dfd_ko_cfg_get_value_from_char(buf_val, &(info_ctrl->int_extra3), line_num);
+ break;
+ default:
+ break;
+ }
+}
+
+/* ADD A CONFIGURATION ITEM */
+static int dfd_ko_cfg_add_info_ctrl_item(uint64_t key, info_ctrl_mem_t member, char *buf_val,
+ int line_num)
+{
+ int rv;
+ info_ctrl_t *info_ctrl_cfg;
+
+ info_ctrl_cfg = lnode_find_node(&dfd_ko_cfg_list_root, key);
+ if (info_ctrl_cfg == NULL) {
+ /* Node does not exist,kmalloc new node */
+ info_ctrl_cfg = (info_ctrl_t *)kmalloc(sizeof(info_ctrl_t), GFP_KERNEL);
+ if (info_ctrl_cfg == NULL) {
+ DBG_DEBUG(DBG_ERROR, "line%d: kmalloc info_ctrl fail\n", line_num);
+ return -1;
+ }
+ mem_clear(info_ctrl_cfg, sizeof(info_ctrl_t));
+
+ /* Add to linked list */
+ dfd_ko_cfg_set_info_ctrl_mem_value(info_ctrl_cfg, member, buf_val, line_num);
+ rv = lnode_insert_node(&dfd_ko_cfg_list_root, key, info_ctrl_cfg);
+ if (rv == 0) {
+ DBG_DEBUG(DBG_VERBOSE, "line%d: add info_ctrl item[%s=%s] success, key=0x%08llx\n",
+ line_num, g_info_ctrl_mem_str[member], buf_val, key);
+ } else {
+ kfree(info_ctrl_cfg);
+ info_ctrl_cfg = NULL;
+ DBG_DEBUG(DBG_ERROR, "line%d: add info_ctrl item[%s=%s] fail, key=0x%08llx rv=%d\n",
+ line_num, g_info_ctrl_mem_str[member], buf_val, key, rv);
+ return -1;
+ }
+ } else {
+ /* If the node already exists, modify the configuration value */
+ DBG_DEBUG(DBG_VERBOSE, "line%d: replace info_ctrl item[%s=%s], key=0x%08llx\n",
+ line_num, g_info_ctrl_mem_str[member], buf_val, key);
+ dfd_ko_cfg_set_info_ctrl_mem_value(info_ctrl_cfg, member, buf_val, line_num);
+ }
+
+ return 0;
+}
+
+/* Parse the configuration of info_ctrl_t */
+static int dfd_ko_cfg_analyse_info_ctrl_item(dfd_cfg_item_id_t cfg_item_id, char *arg_name,
+ char *arg_value, char *cfg_pre, index_range_t *index_range, int line_num)
+{
+ int rv;
+ int index1 = 0, index2 = 0;
+ uint64_t key;
+ char *arg_name_tmp;
+ info_ctrl_mem_t member;
+
+ /* Parsing structure member */
+ arg_name_tmp = arg_name + strlen(cfg_pre);
+ rv = dfd_ko_cfg_get_info_ctrl_member(arg_name_tmp, &member, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ /* Get index value */
+ if (index_range->index1_max != INDEX_NOT_EXIST) {
+ arg_name_tmp += strlen(g_info_ctrl_mem_str[member]);
+ rv = dfd_ko_cfg_get_index(arg_name_tmp, index_range, &index1, &index2, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+ }
+
+ /* ADD A CONFIGURATION ITEM */
+ key = DFD_CFG_KEY(cfg_item_id, index1, index2);
+ rv = dfd_ko_cfg_add_info_ctrl_item(key, member, arg_value, line_num);
+ if (rv < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Parsing configuration */
+static int dfd_ko_cfg_analyse_config(char *arg_name, char*arg_value, int line_num)
+{
+ int i, rv = 0;
+ int cfg_item_num;
+
+ cfg_item_num = sizeof(dfd_cfg_item_name) / sizeof(dfd_cfg_item_name[0]);
+ for (i = 0; i < cfg_item_num; i++) {
+ if (memcmp(arg_name, dfd_cfg_item_name[i], strlen(dfd_cfg_item_name[i])) == 0){
+ if (DFD_CFG_ITEM_IS_INT(i)) {
+ rv = dfd_ko_cfg_analyse_int_item(i, arg_name, arg_value, dfd_cfg_item_name[i],
+ &(dfd_cfg_item_index_range[i]), line_num);
+ } else if (DFD_CFG_ITEM_IS_STRING(i)) {
+ rv = dfd_ko_cfg_analyse_str_item(i, arg_name, arg_value, dfd_cfg_item_name[i],
+ &(dfd_cfg_item_index_range[i]), line_num);
+ } else if (DFD_CFG_ITEM_IS_I2C_DEV(i)) {
+ rv = dfd_ko_cfg_analyse_i2c_dev_item(i, arg_name, arg_value, dfd_cfg_item_name[i],
+ &(dfd_cfg_item_index_range[i]), line_num);
+ } else if (DFD_CFG_ITEM_IS_INFO_CTRL(i)) {
+ rv = dfd_ko_cfg_analyse_info_ctrl_item(i, arg_name, arg_value, dfd_cfg_item_name[i],
+ &(dfd_cfg_item_index_range[i]), line_num);
+ } else {
+ rv = -1;
+ }
+ break;
+ }
+ }
+
+ return rv;
+}
+
+/* Cut the configuration row with '=' */
+static int dfd_ko_cfg_cut_config_line(char *config_line, char *arg_name, char *arg_value)
+{
+ int i, j = 0, k = 0;
+ int len, name_value_flag = 0;
+
+ len = strlen(config_line);
+ for (i = 0; i < len; i++) {
+ if (config_line[i] == '=') {
+ name_value_flag = 1;
+ continue;
+ }
+
+ /* Data before and after cutting equal sign */
+ if (name_value_flag == 0) {
+ arg_name[j++] = config_line[i];
+ } else {
+ arg_value[k++] = config_line[i];
+ }
+ }
+
+ /* Failed to return if the equal sign does not exist */
+ if (name_value_flag == 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+/* Parse configuration row */
+static int dfd_ko_cfg_analyse_config_line(char *config_line, int line_num)
+{
+ int rv;
+ char arg_name[DFD_CFG_NAME_MAX_LEN] = {0};
+ char arg_value[DFD_CFG_VALUE_MAX_LEN] = {0};
+
+ /* Remove all Spaces from the configuration line */
+ dfd_ko_cfg_del_space_lf_cr(config_line);
+
+ /* Blank line */
+ if (strlen(config_line) == 0) {
+ DBG_DEBUG(DBG_VERBOSE, "line%d: space line\n", line_num);
+ return 0;
+ }
+
+ /* Comment line */
+ if (config_line[0] == '#') {
+ DBG_DEBUG(DBG_VERBOSE, "line%d: comment line[%s]\n", line_num, config_line);
+ return 0;
+ }
+
+ /* Look for the '=' character after the line argument and record its position */
+ rv = dfd_ko_cfg_cut_config_line(config_line, arg_name, arg_value);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_VERBOSE, "line%d: [%s]no '=' between name and value\n",
+ line_num, config_line);
+ return -1;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "line%d: config_line[%s] name[%s] value[%s]\n",
+ line_num, config_line, arg_name, arg_value);
+ return dfd_ko_cfg_analyse_config(arg_name, arg_value, line_num);
+}
+
+/* Parse configuration file */
+static int dfd_ko_cfg_analyse_config_file(char *fpath)
+{
+ int rv;
+ int line_num = 1;
+ kfile_ctrl_t kfile_ctrl;
+ char config_line[DFD_CFG_CMDLINE_MAX_LEN] = {0};
+
+ rv = kfile_open(fpath, &kfile_ctrl);
+ if (rv != KFILE_RV_OK) {
+ DBG_DEBUG(DBG_ERROR, "open config file[%s] fail, rv=%d\n", fpath, rv);
+ return -1;
+ }
+
+ /* Parse the configuration rows line by line */
+ while (kfile_gets(config_line, sizeof(config_line), &kfile_ctrl) > 0) {
+ rv = dfd_ko_cfg_analyse_config_line(config_line, line_num++);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "!!!!file[%s] config line[%d %s] analyse fail\n",
+ fpath, line_num - 1, config_line);
+ break;
+ }
+
+ (void)mem_clear(config_line, sizeof(config_line));
+
+ }
+ kfile_close(&kfile_ctrl);
+
+ return rv;
+}
+
+/**
+ * dfd_ko_cfg_get_item - Get configuration item
+ * @key: node key
+ *
+ * @returns: NULL configuration item does not exist, other configuration items are successful
+ */
+void *dfd_ko_cfg_get_item(uint64_t key)
+{
+ return lnode_find_node(&dfd_ko_cfg_list_root, key);
+}
+
+/* Print configuration item */
+static void dfd_ko_cfg_print_item(uint64_t key, const void *cfg)
+{
+ int item_id;
+ dfd_i2c_dev_t *i2c_dev;
+ info_ctrl_t *info_ctrl;
+
+ if (cfg == NULL) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error\n");
+ return;
+ }
+ printk(KERN_INFO "**************************\n");
+ printk(KERN_INFO "key=0x%08llx\n", key);
+
+ item_id = DFD_CFG_ITEM_ID(key);
+ if (DFD_CFG_ITEM_IS_INT(item_id)) {
+ printk(KERN_INFO "int=%d\n", *((int *)cfg));
+ } else if (DFD_CFG_ITEM_IS_I2C_DEV(item_id)) {
+ i2c_dev = (dfd_i2c_dev_t *)cfg;
+ printk(KERN_INFO ".bus=0x%02x\n", i2c_dev->bus);
+ printk(KERN_INFO ".addr=0x%02x\n", i2c_dev->addr);
+ } else if (DFD_CFG_ITEM_IS_INFO_CTRL(item_id)) {
+ info_ctrl = (info_ctrl_t *)cfg;
+ printk(KERN_INFO ".mode=%s\n", g_info_ctrl_mode_str[info_ctrl->mode]);
+ printk(KERN_INFO ".int_cons=%d\n", info_ctrl->int_cons);
+ printk(KERN_INFO ".src=%s\n", g_info_src_str[info_ctrl->src]);
+ printk(KERN_INFO ".frmt=%s\n", g_info_frmt_str[info_ctrl->frmt]);
+ printk(KERN_INFO ".pola=%s\n", g_info_pola_str[info_ctrl->pola]);
+ printk(KERN_INFO ".fpath=%s\n", info_ctrl->fpath);
+ printk(KERN_INFO ".addr=0x%02x\n", info_ctrl->addr);
+ printk(KERN_INFO ".len=%d\n", info_ctrl->len);
+ printk(KERN_INFO ".bit_offset=%d\n", info_ctrl->bit_offset);
+ } else {
+ printk(KERN_INFO "item[%d] error!\n", item_id);
+ }
+}
+
+/**
+ * dfd_ko_cfg_show_item - Display configuration items
+ * @key: node key
+ */
+void dfd_ko_cfg_show_item(uint64_t key)
+{
+ void *cfg;
+
+ cfg = lnode_find_node(&dfd_ko_cfg_list_root, key);
+ if (cfg == 0) {
+ printk(KERN_INFO "item[0x%08llx] not exist\n", key);
+ return;
+ }
+
+ dfd_ko_cfg_print_item(key, cfg);
+}
+
+/* x86 devices get the card type method */
+static int dfd_get_my_dev_type_by_file(void)
+{
+ struct file *fp;
+ loff_t pos;
+ int card_type;
+ char buf[DFD_PID_BUF_LEN];
+ int ret;
+
+ fp= filp_open(DFD_PUB_CARDTYPE_FILE, O_RDONLY, 0);
+ if (IS_ERR(fp)) {
+ DBG_DEBUG(DBG_VERBOSE, "open file fail!\n");
+ return -1;
+ }
+
+ mem_clear(buf, DFD_PID_BUF_LEN);
+ pos = 0;
+ ret = kernel_read(fp, buf, DFD_PRODUCT_ID_LENGTH + 1, &pos);
+ if (ret < 0) {
+ DBG_DEBUG(DBG_VERBOSE, "kernel_read failed, path=%s, addr=0, size=%d, ret=%d\n",
+ DFD_PUB_CARDTYPE_FILE, DFD_PRODUCT_ID_LENGTH + 1, ret);
+ filp_close(fp, NULL);
+ return -1;
+ }
+
+ card_type = simple_strtoul(buf, NULL, 0);
+ DBG_DEBUG(DBG_VERBOSE, "card_type 0x%x.\n", card_type);
+
+ filp_close(fp, NULL);
+ return card_type;
+}
+
+/**
+ * drv_get_my_dev_type - Get device type
+ *
+ * return: Return the corresponding value
+ *
+ */
+static int drv_get_my_dev_type(void)
+{
+ static int type = -1;
+
+ if (type > 0) {
+ return type;
+ }
+ type = dfd_get_my_dev_type_by_file();
+ DBG_DEBUG(DBG_VERBOSE, "ko board type %d\n", type);
+ return type;
+}
+
+static int dfd_ko_cfg_init(void)
+{
+ int rv;
+ int card_type;
+ char file_name[32] = {0};
+ char fpath[128] = {0};
+ kfile_ctrl_t kfile_ctrl;
+
+ /* Initializes the list root node */
+ rv = lnode_init_root(&dfd_ko_cfg_list_root);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "init list root fail, rv=%d\n", rv);
+ return -1;
+ }
+
+ /* Gets the card type */
+ card_type = drv_get_my_dev_type();
+ if (card_type < 0) {
+ DBG_DEBUG(DBG_ERROR, "get my dev type fail, rv=%d\n", card_type);
+ return -1;
+ }
+
+ /* Read the required profile name for the corresponding board type */
+ snprintf(fpath, sizeof(fpath), "%s0x%x", DFD_KO_FILE_NAME_DIR, card_type);
+ rv = kfile_open(fpath, &kfile_ctrl);
+ if (rv != KFILE_RV_OK) {
+ DBG_DEBUG(DBG_ERROR, "open config file[%s] fail, rv=%d\n", fpath, rv);
+ return -1;
+ }
+
+ /* Multiple profiles are supported */
+ while (kfile_gets(file_name, sizeof(file_name), &kfile_ctrl) > 0) {
+ /* Read configuration file */
+ dfd_ko_cfg_del_space_lf_cr(file_name);
+ snprintf(fpath, sizeof(fpath), "%s%s.cfg", DFD_KO_CFG_FILE_DIR, file_name);
+ DBG_DEBUG(DBG_VERBOSE, ">>>>start parsing config file[%s]\n", fpath);
+
+ /* Description Failed to parse the configuration file */
+ rv = dfd_ko_cfg_analyse_config_file(fpath);
+ if (rv < 0) {
+ break;
+ }
+ }
+ kfile_close(&kfile_ctrl);
+
+ /* todo Configure data validity check */
+ return 0;
+}
+
+/**
+ * dfd_dev_cfg_init - Module initialization
+ *
+ * @returns: <0 Fail, or succeed
+ */
+int32_t dfd_dev_cfg_init(void)
+{
+ return dfd_ko_cfg_init();
+}
+
+/**
+ * dfd_dev_cfg_init - Module exit
+ *
+ * @returns: void
+ */
+
+void dfd_dev_cfg_exit(void)
+{
+ lnode_free_list(&dfd_ko_cfg_list_root);
+ val_convert_node_lst_free(&dfd_lib_cfg_led_status_decode_conv_lst);
+ val_convert_node_lst_free(&dfd_lib_cfg_fan_name_conv_dir_lst);
+ val_convert_node_lst_free(&dfd_lib_cfg_power_name_conv_lst);
+ return;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_adapter.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_adapter.c
new file mode 100644
index 000000000000..c4c273059b11
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_adapter.c
@@ -0,0 +1,654 @@
+/*
+ * An dfd_cfg_adapter driver for cfg of adapter devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "wb_module.h"
+#include "dfd_cfg_file.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+
+/* dfd_i2c_dev_t member string */
+char *g_dfd_i2c_dev_mem_str[DFD_I2C_DEV_MEM_END] = {
+ ".bus",
+ ".addr",
+};
+
+static dfd_i2c_dev_t* dfd_ko_get_cpld_i2c_dev(int sub_slot, int cpld_id)
+{
+ uint64_t key;
+ dfd_i2c_dev_t *i2c_dev;
+
+ /* Read configuration value */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_I2C_DEV, sub_slot, cpld_id);
+ i2c_dev = dfd_ko_cfg_get_item(key);
+ if (i2c_dev == NULL) {
+ DBG_DEBUG(DBG_ERROR, "get cpld[%d] i2c dev config fail, key_name=%s\n",
+ cpld_id, key_to_name(DFD_CFG_ITEM_CPLD_I2C_DEV));
+ return NULL;
+ }
+
+ return i2c_dev;
+}
+
+static int dfd_ko_i2c_block_read(int bus, int addr, int offset, uint8_t *buf, uint32_t size)
+{
+ struct file *fp;
+ struct i2c_client client;
+ int i;
+ int rv = 0;
+ char i2c_path[32];
+
+ mem_clear(i2c_path, 32);
+ 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)) {
+ DBG_DEBUG(DBG_ERROR, "i2c open fail.\n");
+ return -1;
+ }
+ memcpy(&client, fp->private_data, sizeof(struct i2c_client));
+ client.addr = addr;
+
+ if (i2c_check_functionality(client.adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ for (i = 0; i < size; i += 32) {
+ rv = i2c_smbus_read_i2c_block_data(&client, offset + i, WB_MIN(32, size-i), buf + i);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "i2c_block read failed, rv = %d\n", rv);
+ rv = -DFD_RV_DEV_FAIL;
+ goto out;
+ }
+ if (rv != 32) {
+ break;
+ }
+ }
+ rv = DFD_RV_OK;
+ } else {
+ rv = -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+out:
+ filp_close(fp, NULL);
+ return rv;
+}
+
+static int32_t dfd_ko_i2c_smbus_transfer(int read_write, int bus, int addr, int offset, uint8_t *buf, uint32_t size)
+{
+ int rv;
+ struct i2c_adapter *i2c_adap;
+ union i2c_smbus_data data;
+
+ i2c_adap = i2c_get_adapter(bus);
+ if (i2c_adap == NULL) {
+ DBG_DEBUG(DBG_ERROR, "get i2c bus[%d] adapter fail\n", bus);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ /* Operation i2c */
+ if (read_write == I2C_SMBUS_WRITE) {
+ data.byte = *buf;
+ } else {
+ data.byte = 0;
+ }
+ rv = i2c_smbus_xfer(i2c_adap, addr, 0, read_write, offset, I2C_SMBUS_BYTE_DATA, &data);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "i2c dev[bus=%d addr=0x%x offset=0x%x size=%d rw=%d] transfer fail, rv=%d\n",
+ bus, addr, offset, size, read_write, rv);
+ rv = -DFD_RV_DEV_FAIL;
+ } else {
+ DBG_DEBUG(DBG_VERBOSE, "i2c dev[bus=%d addr=0x%x offset=0x%x size=%d rw=%d] transfer success\n",
+ bus, addr, offset, size, read_write);
+ rv = DFD_RV_OK;
+ }
+
+ if (read_write == I2C_SMBUS_READ) {
+ if (rv == DFD_RV_OK) {
+ *buf = data.byte;
+ } else {
+ *buf = 0;
+ }
+ }
+
+ i2c_put_adapter(i2c_adap);
+ return rv;
+}
+
+static int32_t dfd_ko_i2c_read_bulk_data(int bus, int addr, int offset, uint8_t *buf, uint32_t size)
+{
+ int i, rv;
+ for (i = 0; i < DFD_KO_CPLD_I2C_RETRY_TIMES; i++) {
+ rv = dfd_ko_i2c_block_read(bus, addr, offset, buf, size);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "[%d] read[offset=0x%x] fail, rv %d\r\n", i, addr, rv);
+ msleep(DFD_KO_CPLD_I2C_RETRY_SLEEP);
+ } else {
+ DBG_DEBUG(DBG_VERBOSE, "[%d] read[offset=0x%x] success\r\n",
+ i, addr);
+ break;
+ }
+ }
+ return rv;
+}
+
+static int32_t dfd_ko_i2c_read_data(int bus, int addr, int offset, uint8_t *buf, uint32_t size)
+{
+ int i, rv;
+ for (i = 0; i < DFD_KO_CPLD_I2C_RETRY_TIMES; i++) {
+ rv = dfd_ko_i2c_smbus_transfer(I2C_SMBUS_READ, bus, addr, offset, buf, size);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "[%d]cpld read[offset=0x%x] fail, rv %d\n", i, addr, rv);
+ msleep(DFD_KO_CPLD_I2C_RETRY_SLEEP);
+ } else {
+ DBG_DEBUG(DBG_VERBOSE, "[%d]cpld read[offset=0x%x] success, value=0x%x\n",
+ i, addr, *buf);
+ break;
+ }
+ }
+ return rv;
+}
+
+static int32_t dfd_ko_i2c_write_data(int bus, int addr, int offset, uint8_t data, uint32_t size)
+{
+ int i, rv;
+ for (i = 0; i < DFD_KO_CPLD_I2C_RETRY_TIMES; i++) {
+ rv = dfd_ko_i2c_smbus_transfer(I2C_SMBUS_WRITE, bus, addr, offset, &data, size);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "[%d]cpld write[offset=0x%x] fail, rv=%d\n", i, addr, rv);
+ msleep(DFD_KO_CPLD_I2C_RETRY_SLEEP);
+ } else {
+ DBG_DEBUG(DBG_VERBOSE, "[%d]cpld write[offset=0x%x, data=%d] success\n", i, addr, data);
+ break;
+ }
+ }
+
+ return rv;
+}
+
+/**
+ * dfd_ko_cpld_i2c_read - cpld read operation
+ * @offset: Offset address
+ * @buf: data
+ *
+ * @returns: <0 Failure, other success
+ */
+static int32_t dfd_ko_cpld_i2c_read(int32_t addr, uint8_t *buf)
+{
+ int rv;
+ int sub_slot, cpld_id, cpld_addr;
+ dfd_i2c_dev_t *i2c_dev;
+
+ if (buf == NULL) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error\n");
+ return -DFD_RV_INDEX_INVALID;
+ }
+
+ /* Obtain the i2c device bus addr */
+ sub_slot = DFD_KO_CPLD_GET_SLOT(addr);
+ cpld_id = DFD_KO_CPLD_GET_ID(addr);
+ cpld_addr = DFD_KO_CPLD_GET_INDEX(addr);
+
+ i2c_dev = dfd_ko_get_cpld_i2c_dev(sub_slot, cpld_id);
+ if (i2c_dev == NULL) {
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ rv = dfd_ko_i2c_read_data(i2c_dev->bus, i2c_dev->addr, cpld_addr, buf, sizeof(uint8_t));
+
+ return rv;
+}
+
+/**
+ * dfd_ko_cpld_i2c_write - cpld WRITE OPERATION
+ * @offset: Offset address
+ * @buf: data
+ *
+ * @returns: <0 Failure, other success
+ */
+static int32_t dfd_ko_cpld_i2c_write(int32_t addr, uint8_t data)
+{
+ int rv;
+ int sub_slot, cpld_id, cpld_addr;
+ dfd_i2c_dev_t *i2c_dev;
+
+ /* Obtain the i2c device bus addr */
+ sub_slot = DFD_KO_CPLD_GET_SLOT(addr);
+ cpld_id = DFD_KO_CPLD_GET_ID(addr);
+ cpld_addr = DFD_KO_CPLD_GET_INDEX(addr);
+
+ i2c_dev = dfd_ko_get_cpld_i2c_dev(sub_slot, cpld_id);
+ if (i2c_dev == NULL) {
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ rv = dfd_ko_i2c_write_data(i2c_dev->bus, i2c_dev->addr, cpld_addr, data, sizeof(uint8_t));
+
+ return rv;
+}
+
+#ifdef CONFIG_X86
+/**
+ * dfd_ko_cpld_io_read - cpld io spatial read operation
+ * @offset: address
+ * @buf: data
+ *
+ * @returns: <0 Failure, other success
+ */
+static int32_t dfd_ko_cpld_io_read(int32_t addr, uint8_t *buf)
+{
+ uint64_t key;
+ int cpld_id, sub_slot, offset;
+ int *tmp;
+ uint16_t io_port;
+
+ sub_slot = DFD_KO_CPLD_GET_SLOT(addr);
+ cpld_id = DFD_KO_CPLD_GET_ID(addr);
+ offset = DFD_KO_CPLD_GET_INDEX(addr);
+
+ /* int Type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_LPC_DEV, sub_slot, cpld_id);
+ tmp = dfd_ko_cfg_get_item(key);
+ if (tmp == NULL) {
+ DBG_DEBUG(DBG_ERROR,"get cpld io base config fail, key_name=%s\n",
+ key_to_name(DFD_CFG_ITEM_CPLD_LPC_DEV));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ io_port = (u16)(*tmp) + offset;
+ *buf = inb(io_port);
+ DBG_DEBUG(DBG_VERBOSE, "read cpld io port addr 0x%x, data 0x%x\n", io_port, *buf);
+
+ return DFD_RV_OK;
+
+}
+#endif
+
+#ifdef CONFIG_X86
+/**
+ * dfd_ko_cpld_io_write - cpld io space WRITE OPERATION
+ * @addr: address
+ * @data: data
+ *
+ * @returns: <0 Failure, other success
+ */
+static int32_t dfd_ko_cpld_io_write(int32_t addr, uint8_t data)
+{
+ uint64_t key;
+ int cpld_id, sub_slot, offset;
+ int *tmp;
+ uint16_t io_port;
+
+ sub_slot = DFD_KO_CPLD_GET_SLOT(addr);
+ cpld_id = DFD_KO_CPLD_GET_ID(addr);
+ offset = DFD_KO_CPLD_GET_INDEX(addr);
+
+ /* int Type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_LPC_DEV, sub_slot, cpld_id);
+ tmp = dfd_ko_cfg_get_item(key);
+ if (tmp == NULL) {
+ DBG_DEBUG(DBG_ERROR, "get cpld io base config fail, key_name=%s\n",
+ key_to_name(DFD_CFG_ITEM_CPLD_LPC_DEV));
+ return -1;
+ }
+
+ io_port = (u16)(*tmp) + offset;
+ DBG_DEBUG(DBG_VERBOSE, "write cpld io port addr 0x%x, data 0x%x\n", io_port, data);
+ outb(data, (u16)io_port);
+
+ return DFD_RV_OK;
+}
+#endif
+
+static int dfd_cfg_get_cpld_mode(int sub_slot, int cpld_id, int *mode)
+{
+ uint64_t key;
+ char *name;
+
+ if (mode == NULL) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error\n");
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* string type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_MODE, sub_slot, cpld_id);
+ name = dfd_ko_cfg_get_item(key);
+ if (name == NULL) {
+ DBG_DEBUG(DBG_ERROR, "get cpld[%d] mode info ctrl fail, key_name=%s\n",
+ cpld_id, key_to_name(DFD_CFG_ITEM_CPLD_MODE));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "cpld_id %d mode_name %s.\n", cpld_id, name);
+ if (!strncmp(name, DFD_KO_CPLD_MODE_I2C_STRING, strlen(DFD_KO_CPLD_MODE_I2C_STRING))) {
+ *mode = DFD_CPLD_MODE_I2C;
+ } else if (!strncmp(name, DFD_KO_CPLD_MODE_LPC_STRING, strlen(DFD_KO_CPLD_MODE_LPC_STRING))) {
+ *mode = DFD_CPLD_MODE_LPC;
+ } else {
+ /* The default mode is I2C */
+ *mode = DFD_CPLD_MODE_I2C;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "cpld_id %d mode %d.\n", cpld_id, *mode);
+ return 0;
+}
+
+/**
+ * dfd_ko_cpld_read - cpld read operation, read only one byte
+ * @offset: Offset address
+ * @buf: data
+ *
+ * @returns: <0 Failure, other success
+ */
+int32_t dfd_ko_cpld_read(int32_t addr, uint8_t *buf)
+{
+ int ret;
+ int sub_slot, cpld_id;
+ int cpld_mode;
+
+ sub_slot = DFD_KO_CPLD_GET_SLOT(addr);
+ cpld_id = DFD_KO_CPLD_GET_ID(addr);
+ /* cpld mode, including I2C and LPC. Other modes are not supported */
+ ret = dfd_cfg_get_cpld_mode(sub_slot, cpld_id, &cpld_mode);
+ if (ret) {
+ DBG_DEBUG(DBG_WARN, "drv_get_cpld_mode sub_slot %d cpldid %d faile, set default i2c mode.\n", sub_slot, cpld_id);
+ cpld_mode = DFD_CPLD_MODE_I2C;
+ }
+
+ if (cpld_mode == DFD_CPLD_MODE_I2C) {
+ ret = dfd_ko_cpld_i2c_read(addr, buf);
+ } else if (cpld_mode == DFD_CPLD_MODE_LPC) {
+#ifdef CONFIG_X86
+ ret = dfd_ko_cpld_io_read(addr, buf);
+#else
+ DBG_DEBUG(DBG_ERROR, "ERROR:only x86 arch support cpld_mode %d.\n", cpld_mode);
+ ret = -DFD_RV_DEV_NOTSUPPORT;
+#endif
+ } else {
+ DBG_DEBUG(DBG_ERROR, "cpld_mode %d invalid.\n", cpld_mode);
+ ret = -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "addr 0x%x val 0x%x ret %d\n", addr, *buf, ret);
+ return ret;
+}
+
+/**
+ * dfd_ko_cpld_write - cpld WRITE OPERATION Write a byte
+ * @offset: Offset address
+ * @buf: data
+ *
+ * @returns: <0 Failure, other success
+ */
+int32_t dfd_ko_cpld_write(int32_t addr, uint8_t val)
+{
+ int ret;
+ int sub_slot, cpld_id, cpld_mode;
+
+ sub_slot = DFD_KO_CPLD_GET_SLOT(addr);
+ cpld_id = DFD_KO_CPLD_GET_ID(addr);
+
+ ret = dfd_cfg_get_cpld_mode(sub_slot, cpld_id, &cpld_mode);
+ if (ret) {
+ DBG_DEBUG(DBG_ERROR, "drv_get_cpld_mode sub_slot %d cpldid %d faile, set default local_bus mode.\n", sub_slot, cpld_id);
+ cpld_mode = DFD_CPLD_MODE_I2C;
+ }
+
+ if (cpld_mode == DFD_CPLD_MODE_I2C) {
+ ret = dfd_ko_cpld_i2c_write(addr, val);
+ } else if (cpld_mode == DFD_CPLD_MODE_LPC) {
+#ifdef CONFIG_X86
+ ret = dfd_ko_cpld_io_write(addr, val);
+#else
+ DBG_DEBUG(DBG_ERROR, "ERROR:only x86 arch support cpld_mode %d.\n", cpld_mode);
+ ret = -DFD_RV_DEV_NOTSUPPORT;
+#endif
+ } else {
+ DBG_DEBUG(DBG_ERROR, "cpld_mode %d invalid.\n", cpld_mode);
+ ret = -DFD_RV_MODE_INVALID;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "addr 0x%x val 0x%x ret %d\n", addr, val, ret);
+ return ret;
+}
+
+/**
+ * dfd_ko_i2c_read_tmp - I2C read operation
+ * @bus: I2C BUS Device address
+ * @offset:Register offset
+ * @buf:Read buffer
+ * @size:Read length
+ * @returns: <0 Failure, other success
+ */
+static int32_t dfd_ko_i2c_read_tmp(int bus, int addr, int offset, uint8_t *buf, uint32_t size)
+{
+ int i, rv;
+
+ for (i = 0; i < size; i++) {
+ rv = dfd_ko_i2c_read_data(bus, addr, offset, &buf[i], sizeof(uint8_t));
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "dfd_ko_i2c_read_data[bus=%d addr=0x%x offset=0x%x]fail, rv=%d\n",
+ bus, addr, offset, rv);
+ return rv;
+ }
+ offset++;
+ }
+
+ return size;
+}
+
+/**
+ * dfd_ko_i2c_write - I2C WRITE OPERATION
+ * @bus: I2C BUS
+ * @addr: I2C Device address
+ * @offset:Register offset
+ * @buf: Write buffer
+ * @size:Write length
+ * @returns: <0 Failure, other success
+ */
+int32_t dfd_ko_i2c_write(int bus, int addr, int offset, uint8_t *buf, uint32_t size)
+{
+ int i, rv;
+
+ for (i = 0; i < size; i++) {
+ rv = dfd_ko_i2c_write_data(bus, addr, offset, buf[i], sizeof(uint8_t));
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "dfd_ko_i2c_write[bus=%d addr=0x%x offset=0x%x]fail, rv=%d\n",
+ bus, addr, offset, rv);
+ return rv;
+ }
+ offset++;
+ }
+
+ return size;
+
+}
+
+/**
+ * dfd_ko_read_file - File read operation
+ * @fpath: File path
+ * @addr: address
+ * @val: data
+ * @read_bytes: length
+ *
+ * @returns: <0 Failure, other success
+ */
+int32_t dfd_ko_read_file(char *fpath, int32_t addr, uint8_t *val, int32_t read_bytes)
+{
+ int32_t ret;
+ struct file *filp;
+ loff_t pos;
+
+ struct kvec iov = {
+ .iov_base = val,
+ .iov_len = min_t(size_t, read_bytes, MAX_RW_COUNT),
+ };
+ struct iov_iter iter;
+
+ if ((fpath == NULL) || (val == NULL) || (addr < 0) || (read_bytes < 0)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error, addr=%d read_bytes=%d\n", addr, read_bytes);
+ return -DFD_RV_INDEX_INVALID;
+ }
+
+ /* Open file */
+ filp = filp_open(fpath, O_RDONLY, 0);
+ if (IS_ERR(filp)) {
+ DBG_DEBUG(DBG_ERROR, "open file[%s] fail\n", fpath);
+ return -DFD_RV_DEV_FAIL;
+ }
+ /* Location file */
+ pos = addr;
+ iov_iter_kvec(&iter, ITER_DEST, &iov, 1, iov.iov_len);
+ ret = vfs_iter_read(filp, &iter, &pos, 0);
+ if (ret < 0) {
+ DBG_DEBUG(DBG_ERROR, "vfs_iter_read failed, path=%s, addr=%d, size=%d, ret=%d\n", fpath, addr, read_bytes, ret);
+ ret = -DFD_RV_DEV_FAIL;
+ }
+ filp_close(filp, NULL);
+ return ret;
+}
+
+/**
+ * dfd_ko_other_i2c_dev_read - other_i2c read operation
+ * @addr: address
+ * @val: data
+ * @read_bytes: length
+ *
+ * @returns: <0 Failure, other success
+ */
+int32_t dfd_ko_other_i2c_dev_read(int32_t addr, uint8_t *value, int32_t read_len)
+{
+ uint64_t key;
+ int rv;
+ int e2p_main_id, e2p_index, e2p_addr;
+ dfd_i2c_dev_t *i2c_dev;
+
+ if ((value == NULL) || (read_len <= 0)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error, read_len=%d\r\n", read_len);
+ return -1;
+ }
+
+ e2p_main_id = DFD_KO_OTHER_I2C_GET_MAIN_ID(addr);
+ e2p_index = DFD_KO_OTHER_I2C_GET_INDEX(addr);
+ e2p_addr = DFD_KO_OTHER_I2C_GET_OFFSET(addr);
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_OTHER_I2C_DEV, e2p_main_id, e2p_index);
+ i2c_dev = dfd_ko_cfg_get_item(key);
+ if (i2c_dev == NULL) {
+ DBG_DEBUG(DBG_ERROR, "psu i2c dev config error, key_name: %s\r\n",
+ key_to_name(DFD_CFG_ITEM_OTHER_I2C_DEV));
+ return -DFD_RV_NODE_FAIL;
+ }
+
+ rv = dfd_ko_i2c_read_bulk_data(i2c_dev->bus, i2c_dev->addr, e2p_addr, value, read_len);
+ DBG_DEBUG(DBG_VERBOSE, "dfd_ko_other_i2c_dev_read, value[0] = 0x%x\n", value[0]);
+ DBG_DEBUG(DBG_VERBOSE, "dfd_ko_other_i2c_dev_read, value[1] = 0x%x\n", value[1]);
+ return rv;
+}
+
+/**
+ * dfd_ko_i2c_read - I2C read operation
+ * @bus: I2C BUS
+ * @addr: I2C Device address
+ * @offset:Register offset
+ * @buf:Read buffer
+ * @size:Read length
+ * @sysfs_name:sysfs attribute name
+ * @returns: <0 Failure, other success
+ */
+int32_t dfd_ko_i2c_read(int bus, int addr, int offset, uint8_t *buf, uint32_t size, const char *sysfs_name)
+{
+ int rv;
+ char sysfs_path[DFD_SYSFS_PATH_MAX_LEN];
+
+ if (buf == NULL) {
+ DBG_DEBUG(DBG_ERROR, "params error, buf is NULL.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ if (sysfs_name == NULL) { /* Read in i2c mode */
+ DBG_DEBUG(DBG_VERBOSE, "using i2c_smbus_xfer, bus:%d, addr:0x%x, offset:0x%x, read size:%d.\n",
+ bus, addr, offset, size);
+ rv = dfd_ko_i2c_read_tmp(bus, addr, offset, buf, size);
+ } else { /* Read by sysfs */
+ mem_clear(sysfs_path, sizeof(sysfs_path));
+ snprintf(sysfs_path, sizeof(sysfs_path), "/sys/bus/i2c/devices/%d-%04x/%s",
+ bus, addr, sysfs_name);
+ DBG_DEBUG(DBG_VERBOSE, "using sysfs, sysfs_path:%s, offset:0x%x, read size:%d.\n",
+ sysfs_path, offset, size);
+ rv = dfd_ko_read_file(sysfs_path, offset, buf, size);
+ }
+
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "dfd_ko_i2c_read failed.\n");
+ } else {
+ DBG_DEBUG(DBG_VERBOSE, "dfd_ko_i2c_read success.\n");
+ }
+
+ return rv;
+}
+
+/**
+ * dfd_ko_write_file - file WRITE OPERATION
+ * @fpath: file path
+ * @addr: address
+ * @val: data
+ * @write_bytes: length
+ *
+ * @returns: <0 Failure, other success
+ */
+int32_t dfd_ko_write_file(char *fpath, int32_t addr, uint8_t *val, int32_t write_bytes)
+{
+ int32_t ret;
+ struct file *filp;
+ loff_t pos;
+
+ struct kvec iov = {
+ .iov_base = val,
+ .iov_len = min_t(size_t, write_bytes, MAX_RW_COUNT),
+ };
+ struct iov_iter iter;
+
+ if ((fpath == NULL) || (val == NULL) || (addr < 0) || (write_bytes <= 0)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error, addr=%d write_bytes=%d\n", addr, write_bytes);
+ return -DFD_RV_INDEX_INVALID;
+ }
+
+ /* Open file */
+ filp = filp_open(fpath, O_RDWR, 777);
+ if (IS_ERR(filp)) {
+ DBG_DEBUG(DBG_ERROR, "open file[%s] fail\n", fpath);
+ return -DFD_RV_DEV_FAIL;
+ }
+ /* Location file */
+ pos = addr;
+ iov_iter_kvec(&iter, ITER_SOURCE, &iov, 1, iov.iov_len);
+ ret = vfs_iter_write(filp, &iter, &pos, 0);
+ if (ret < 0) {
+ DBG_DEBUG(DBG_ERROR,"vfs_iter_write failed, path=%s, addr=%d, size=%d, ret=%d\n", fpath, addr, write_bytes, ret);
+ ret = -DFD_RV_DEV_FAIL;
+ }
+ vfs_fsync(filp, 1);
+ filp_close(filp, NULL);
+ return ret;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_file.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_file.c
new file mode 100644
index 000000000000..7164e02d90f2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_file.c
@@ -0,0 +1,305 @@
+/*
+ * An dfd_cfg_file driver for cfg of file devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "dfd_cfg_file.h"
+#include "wb_module.h"
+
+struct getdents_callback {
+ struct dir_context ctx;
+ const char *obj_name; /* Name to be matched */
+ char *match_name; /* Matching result */
+ int dir_len; /* Directory name length */
+ int found; /* Configuration flag */
+};
+
+/*
+ * Open file
+ * @fname: filename
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: 0 Success, other failure
+ */
+int kfile_open(char *fname, kfile_ctrl_t *kfile_ctrl)
+{
+ int ret;
+ struct file *filp;
+ loff_t pos;
+
+ if ((fname == NULL) || (kfile_ctrl == NULL)) {
+ return KFILE_RV_INPUT_ERR;
+ }
+
+ /* Open file */
+ filp = filp_open(fname, O_RDONLY, 0);
+ if (IS_ERR(filp)) {
+ return KFILE_RV_OPEN_FAIL;
+ }
+
+ kfile_ctrl->size = filp->f_inode->i_size;
+
+ /* Request file size memory */
+ kfile_ctrl->buf = kmalloc(kfile_ctrl->size, GFP_KERNEL);
+ if (kfile_ctrl->buf == NULL) {
+ ret = KFILE_RV_MALLOC_FAIL;
+ goto close_fp;
+ }
+ mem_clear(kfile_ctrl->buf, kfile_ctrl->size);
+ /* Read file contents */
+ pos = 0;
+ ret = kernel_read(filp, kfile_ctrl->buf, kfile_ctrl->size, &pos);
+ if (ret < 0) {
+ ret = KFILE_RV_RD_FAIL;
+ goto free_buf;
+ }
+ /* Set current position */
+ kfile_ctrl->pos = 0;
+
+ ret = KFILE_RV_OK;
+ goto close_fp;
+
+free_buf:
+ kfree(kfile_ctrl->buf);
+ kfile_ctrl->buf = NULL;
+
+close_fp:
+ filp_close(filp, NULL);
+ return ret;
+}
+
+/*
+ * Close file
+ * @kfile_ctrl: File control variable
+ */
+void kfile_close(kfile_ctrl_t *kfile_ctrl)
+{
+ if (kfile_ctrl == NULL) {
+ return;
+ }
+
+ /* Set the file size to 0 to free memory */
+ kfile_ctrl->size = 0;
+ kfile_ctrl->pos = 0;
+ if (kfile_ctrl->buf) {
+ kfree(kfile_ctrl->buf);
+ kfile_ctrl->buf = NULL;
+ }
+}
+
+/*
+ * Get a row
+ * @buf: buf Buffer area
+ * @buf_size: buf size
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: >=0 Success, other failure
+ */
+int kfile_gets(char *buf, int buf_size, kfile_ctrl_t *kfile_ctrl)
+{
+ int i;
+ int has_cr = 0;
+
+ if ((buf == NULL) || (buf_size <= 0) || (kfile_ctrl == NULL) || (kfile_ctrl->buf == NULL)
+ || (kfile_ctrl->size <= 0)) {
+ return KFILE_RV_INPUT_ERR;
+ }
+
+ /* Clear the buf first */
+ mem_clear(buf, buf_size);
+ for (i = 0; i < buf_size; i++) {
+ /* It's at the end of the file */
+ if (kfile_ctrl->pos >= kfile_ctrl->size) {
+ break;
+ }
+
+ /* The previous data is a newline character, and a line has been copied */
+ if (has_cr) {
+ break;
+ }
+
+ /* Search for a newline */
+ if (IS_CR(kfile_ctrl->buf[kfile_ctrl->pos])) {
+ has_cr = 1;
+ }
+
+ /* Copy data */
+ buf[i] = kfile_ctrl->buf[kfile_ctrl->pos];
+ kfile_ctrl->pos++;
+ }
+
+ return i;
+}
+
+/*
+ * Read data
+ * @buf: buf Buffer area
+ * @buf_size: buf size
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: >=0 Success, other failure
+ */
+int kfile_read(int32_t addr, char *buf, int buf_size, kfile_ctrl_t *kfile_ctrl)
+{
+ int i;
+
+ if ((buf == NULL) || (buf_size <= 0) || (kfile_ctrl == NULL) || (kfile_ctrl->buf == NULL)
+ || (kfile_ctrl->size <= 0)) {
+ return KFILE_RV_INPUT_ERR;
+ }
+
+ /* Address check */
+ if ((addr < 0) || (addr >= kfile_ctrl->size)) {
+ return KFILE_RV_ADDR_ERR;
+ }
+
+ /* Clear the buf first */
+ mem_clear(buf, buf_size);
+
+ kfile_ctrl->pos = addr;
+ for (i = 0; i < buf_size; i++) {
+ /* It's at the end of the file */
+ if (kfile_ctrl->pos >= kfile_ctrl->size) {
+ break;
+ }
+
+ /* Copy data */
+ buf[i] = kfile_ctrl->buf[kfile_ctrl->pos];
+ kfile_ctrl->pos++;
+ }
+
+ return i;
+}
+
+static bool kfile_filldir_one(struct dir_context *ctx, const char * name, int len,
+ loff_t pos, u64 ino, unsigned int d_type)
+{
+ struct getdents_callback *buf;
+ bool result;
+ buf = container_of(ctx, struct getdents_callback, ctx);
+ result = 1;
+ if (strncmp(buf->obj_name, name, strlen(buf->obj_name)) == 0) {
+ if (buf->dir_len < len) {
+ DBG_DEBUG(DBG_ERROR, "match ok. dir name:%s, but buf_len %d small than dir len %d.\n",
+ name, buf->dir_len, len);
+ buf->found = 0;
+ return 0;
+ }
+ mem_clear(buf->match_name, buf->dir_len);
+ memcpy(buf->match_name, name, len);
+ buf->found = 1;
+ result = 0;
+ }
+ return result;
+}
+
+/*
+ * Read data
+ * @buf: buf Buffer area
+ * @buf_size: buf size
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: >=0 Success, other failure
+ */
+int kfile_iterate_dir(const char *dir_path, const char *obj_name, char *match_name, int len)
+{
+ int ret;
+ struct file *dir;
+ struct getdents_callback buffer = {
+ .ctx.actor = kfile_filldir_one,
+ };
+
+ if (!dir_path || !obj_name || !match_name) {
+ DBG_DEBUG(DBG_ERROR, "params error. \n");
+ return KFILE_RV_INPUT_ERR;
+ }
+ buffer.obj_name = obj_name;
+ buffer.match_name = match_name;
+ buffer.dir_len = len;
+ buffer.found = 0;
+ /* Open folde */
+ dir = filp_open(dir_path, O_RDONLY, 0);
+ if (IS_ERR(dir)) {
+ DBG_DEBUG(DBG_ERROR, "filp_open error, dir path:%s\n", dir_path);
+ return KFILE_RV_OPEN_FAIL;
+ }
+ ret = iterate_dir(dir, &buffer.ctx);
+ if (buffer.found) {
+ DBG_DEBUG(DBG_VERBOSE, "match ok, dir name:%s\n", match_name);
+ filp_close(dir, NULL);
+ return DFD_RV_OK;
+ }
+ filp_close(dir, NULL);
+ return -DFD_RV_NODE_FAIL;
+}
+
+#if 0
+/*
+ * Write data
+ * @fname: indicates the file name
+ * @addr: offset address of the file to be written
+ * @buf: Writes data
+ * @buf_size: indicates the data size
+ *
+ * @returns: >=0 Success, others fail
+ */
+int kfile_write(char *fpath, int32_t addr, char *buf, int buf_size)
+{
+ int ret = KFILE_RV_OK;
+ struct file *filp;
+ int wlen;
+
+ if ((fpath == NULL) || (buf == NULL) || (buf_size <= 0)) {
+ return KFILE_RV_INPUT_ERR;
+ }
+
+ /* Address check */
+ if (addr < 0) {
+ return KFILE_RV_ADDR_ERR;
+ }
+
+ /* Open file */
+ filp = filp_open(fpath, O_RDWR, 0);
+ if (IS_ERR(filp)) {
+ return KFILE_RV_OPEN_FAIL;
+ }
+
+ filp->f_op->llseek(filp,0,0);
+ filp->f_pos = addr;
+ /* Write file content */
+ wlen = filp->f_op->write(filp, buf, buf_size, &(filp->f_pos));
+ if (wlen < 0) {
+ ret = KFILE_RV_WR_FAIL;
+ }
+
+ filp->f_op->llseek(filp,0,0);
+ filp_close(filp, NULL);
+
+ return ret;
+}
+#endif
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_info.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_info.c
new file mode 100644
index 000000000000..615285d1c326
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_info.c
@@ -0,0 +1,929 @@
+/*
+ * An dfd_cfg_info driver for cfg of information devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_info.h"
+#include "dfd_cfg_file.h"
+
+#define DFD_HWMON_NAME "hwmon"
+
+/* CPLD_VOLATGE_VALUE_MODE1 */
+/* high 8 bit + high 4 bit(bit4-bit7) */
+#define DFD_GET_CPLD_VOLATGE_CODE_VALUE(value) ((value >> 4)& 0xfff)
+#define DFD_GET_CPLD_VOLATGE_REAL_VALUE(code_val, k) ((code_val * 16 * 33 * k) / ((65536 - 5000) * 10))
+
+/* CPLD_VOLATGE_VALUE_MODE2 */
+/* high 8 bit + low 4 bit(bit0-bit3) */
+#define DFD_GET_CPLD_VOLATGE_CODE_VALUE2(value) (((value & 0xff00) >> 4) + (value & 0xf))
+#define DFD_GET_CPLD_VOLATGE_REAL_VALUE2(code_val, k) ((code_val * 33 * k) / 40950)
+
+typedef enum cpld_volatge_value_s {
+ CPLD_VOLATGE_VALUE_MODE1,
+ CPLD_VOLATGE_VALUE_MODE2,
+} cpld_volatge_value_t;
+
+#define VALID_MAC_TEMP_MAX (120)
+#define VALID_MAC_TEMP_MIN (-40)
+#define MAC_TEMP_INVALID (-99999999)
+
+/* info_ctrl_t member string */
+char *g_info_ctrl_mem_str[INFO_CTRL_MEM_END] = {
+ ".mode",
+ ".int_cons",
+ ".src",
+ ".frmt",
+ ".pola",
+ ".fpath",
+ ".addr",
+ ".len",
+ ".bit_offset",
+ ".str_cons",
+ ".int_extra1",
+ ".int_extra2",
+ ".int_extra3",
+};
+
+/* info_ctrl_mode_t enumeration string */
+char *g_info_ctrl_mode_str[INFO_CTRL_MODE_END] = {
+ "none",
+ "config",
+ "constant",
+ "tlv",
+ "str_constant",
+};
+
+/* info_src_t enumeration string */
+char *g_info_src_str[INFO_SRC_END] = {
+ "none",
+ "cpld",
+ "fpga",
+ "other_i2c",
+ "file",
+};
+
+/* info_frmt_t enumeration string */
+char *g_info_frmt_str[INFO_FRMT_END] = {
+ "none",
+ "bit",
+ "byte",
+ "num_bytes",
+ "num_str",
+ "num_buf",
+ "buf",
+};
+
+/* info_pola_t enumeration string */
+char *g_info_pola_str[INFO_POLA_END] = {
+ "none",
+ "positive",
+ "negative",
+};
+
+/* Read information from the cpld */
+static int dfd_read_info_from_cpld(int32_t addr, int read_bytes, uint8_t *val)
+{
+ int i, rv;
+
+ for (i = 0; i < read_bytes; i++) {
+ rv = dfd_ko_cpld_read(addr, &(val[i]));
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "read info[addr=0x%x read_bytes=%d] from cpld fail, reading_byte=%d rv=%d\n",
+ addr, read_bytes, i, rv);
+ return rv;
+ }
+ addr++;
+ }
+
+ return read_bytes;
+}
+
+/* Write information to the cpld */
+static int dfd_write_info_to_cpld(int32_t addr, int write_bytes, uint8_t *val, uint8_t bit_mask)
+{
+ int rv;
+ uint8_t val_tmp;
+
+ val_tmp = val[0];
+ rv = dfd_ko_cpld_write(addr, val_tmp);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "write info[addr=0x%x val=0x%x] to cpld fail, rv=%d\n", addr, val_tmp, rv);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Read information from other_i2c */
+static int dfd_read_info_from_other_i2c(int32_t addr, int read_bytes, uint8_t *val)
+{
+ int rv;
+
+ rv = dfd_ko_other_i2c_dev_read(addr, val, read_bytes);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "read info[addr=0x%x read_bytes=%d] from othre i2c fail, rv=%d\r\n",
+ addr, read_bytes, rv);
+ return rv;
+ }
+
+ return read_bytes;
+}
+
+/* Read information */
+static int dfd_read_info(info_src_t src, char *fpath, int32_t addr, int read_bytes, uint8_t *val)
+{
+ int rv = 0;
+
+ /* Read data from different sources */
+ switch (src) {
+ case INFO_SRC_CPLD:
+ rv = dfd_read_info_from_cpld(addr, read_bytes, val);
+ break;
+ case INFO_SRC_FPGA:
+ rv = -1;
+ DBG_DEBUG(DBG_ERROR, "not support read info from fpga\n");
+ break;
+ case INFO_SRC_OTHER_I2C:
+ rv = dfd_read_info_from_other_i2c(addr, read_bytes, val);
+ break;
+ case INFO_SRC_FILE:
+ rv = dfd_ko_read_file(fpath, addr, val, read_bytes);
+ break;
+ default:
+ rv = -1;
+ DBG_DEBUG(DBG_ERROR, "info src[%d] error\n", src);
+ break;
+ }
+
+ return rv;
+}
+
+/* Write message */
+static int dfd_write_info(info_src_t src, char *fpath, int32_t addr, int write_bytes, uint8_t *val, uint8_t bit_mask)
+{
+ int rv = 0;
+
+ /* Write data to separate sources */
+ switch (src) {
+ case INFO_SRC_CPLD:
+ rv = dfd_write_info_to_cpld(addr, write_bytes, val, bit_mask);
+ break;
+ case INFO_SRC_FPGA:
+ rv = -1;
+ DBG_DEBUG(DBG_ERROR, "not support write info to fpga\n");
+ break;
+ case INFO_SRC_OTHER_I2C:
+ rv = -1;
+ DBG_DEBUG(DBG_ERROR, "not support write info to other i2c\n");
+ break;
+ case INFO_SRC_FILE:
+ rv = dfd_ko_write_file(fpath, addr, val, write_bytes);
+ break;
+ default:
+ rv = -1;
+ DBG_DEBUG(DBG_ERROR, "info src[%d] error\n", src);
+ break;
+ }
+
+ return rv;
+}
+
+static int dfd_get_info_value(info_ctrl_t *info_ctrl, int *ret, info_num_buf_to_value_f pfun)
+{
+ int i, rv;
+ int read_bytes, readed_bytes, int_tmp;
+ uint8_t byte_tmp, val[INFO_INT_MAX_LEN + 1] = {0};
+
+ if (info_ctrl->mode == INFO_CTRL_MODE_CONS) {
+ *ret = info_ctrl->int_cons;
+ return DFD_RV_OK;
+ }
+ if (info_ctrl->mode == INFO_CTRL_MODE_TLV) {
+ return INFO_CTRL_MODE_TLV;
+ }
+
+ if (IS_INFO_FRMT_BIT(info_ctrl->frmt)) {
+ if (!INFO_BIT_OFFSET_VALID(info_ctrl->bit_offset)) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl bit_offsest[%d] invalid\n",
+ info_ctrl->bit_offset);
+ return -DFD_RV_TYPE_ERR;
+ }
+ read_bytes = 1;
+ } else if (IS_INFO_FRMT_BYTE(info_ctrl->frmt) || IS_INFO_FRMT_NUM_STR(info_ctrl->frmt)
+ || IS_INFO_FRMT_NUM_BUF(info_ctrl->frmt)) {
+ if (!INFO_INT_LEN_VALAID(info_ctrl->len)) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl len[%d] invalid\n", info_ctrl->len);
+ return -DFD_RV_TYPE_ERR;
+ }
+ read_bytes = info_ctrl->len;
+ } else {
+ DBG_DEBUG(DBG_ERROR, "info ctrl info format[%d] error\n", info_ctrl->frmt);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ readed_bytes = dfd_read_info(info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, read_bytes, &(val[0]));
+ if (readed_bytes <= 0) {
+ DBG_DEBUG(DBG_ERROR, "read int info[src=%s frmt=%s fpath=%s addr=0x%x read_bytes=%d] fail, rv=%d\n",
+ g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], info_ctrl->fpath,
+ info_ctrl->addr, read_bytes, readed_bytes);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ if (IS_INFO_FRMT_BIT(info_ctrl->frmt)) {
+ if (info_ctrl->pola == INFO_POLA_NEGA) {
+ val[0] = ~val[0];
+ }
+ byte_tmp = (val[0] >> info_ctrl->bit_offset) & (~(0xff << info_ctrl->len));
+ if (pfun) {
+ rv = pfun(&byte_tmp, sizeof(byte_tmp), &int_tmp);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl bit process fail, rv=%d\n", rv);
+ return rv;
+ }
+ } else {
+ int_tmp = (int)byte_tmp;
+ }
+ } else if (IS_INFO_FRMT_BYTE(info_ctrl->frmt)) {
+ int_tmp = 0;
+ for (i = 0; i < info_ctrl->len; i++) {
+ if (info_ctrl->pola == INFO_POLA_NEGA) {
+ int_tmp |= val[info_ctrl->len - i - 1];
+ } else {
+ int_tmp |= val[i];
+ }
+ if (i != (info_ctrl->len - 1)) {
+ int_tmp <<= 8;
+ }
+ }
+ } else if (IS_INFO_FRMT_NUM_STR(info_ctrl->frmt)) {
+ val[readed_bytes] = '\0';
+ int_tmp = simple_strtol((char *)(&(val[0])), NULL, 10);
+ } else {
+ if (pfun == NULL) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl number buf process function is null\n");
+ return -DFD_RV_INDEX_INVALID;
+ }
+ rv = pfun(val, readed_bytes, &int_tmp);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl number buf process fail, rv=%d\n", rv);
+ return rv;
+ }
+ }
+
+ *ret = int_tmp;
+ DBG_DEBUG(DBG_VERBOSE, "read int info[src=%s frmt=%s pola=%s fpath=%s addr=0x%x len=%d bit_offset=%d] success, ret=%d\n",
+ g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], g_info_pola_str[info_ctrl->pola],
+ info_ctrl->fpath, info_ctrl->addr, info_ctrl->len, info_ctrl->bit_offset, *ret);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_info_get_int - Get int type information
+ * @key: Search keyword of the configuration item
+ * @ret: int type information
+ * @pfun: num buf type data conversion function
+ *
+ * @returns: 0 Success, <0 failure
+ */
+int dfd_info_get_int(uint64_t key, int *ret, info_num_buf_to_value_f pfun)
+{
+ int rv;
+ info_ctrl_t *info_ctrl;
+
+ if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key)) || (ret == NULL)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error, key=0x%08llx\n", key);
+ return -DFD_RV_INDEX_INVALID;
+ }
+
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "get info ctrl value, key=0x%08llx\n", key);
+ rv = dfd_get_info_value(info_ctrl, ret, pfun);
+ return rv;
+}
+
+/**
+ * dfd_info_get_buf - Get buf type information
+ * @key: Search keyword of the configuration item
+ * @buf: information buf
+ * @buf_len: buf length, which must be no less than info_ctrl->len
+ * @pfun: Data conversion function pointer
+ *
+ * @returns: <0 Success, <0 failure
+ */
+int dfd_info_get_buf(uint64_t key, uint8_t *buf, int buf_len, info_buf_to_buf_f pfun)
+{
+ int rv;
+ int read_bytes, buf_real_len;
+ uint8_t buf_tmp[INFO_BUF_MAX_LEN];
+ info_ctrl_t *info_ctrl;
+
+ /* Entry check */
+ if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key)) || (buf == NULL)) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error, key=0x%08llx\n", key);
+ return -DFD_RV_INDEX_INVALID;
+ }
+
+ /* Get the configuration item read and write control variables */
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ /* Failed to return the non-configured mode */
+ if (info_ctrl->mode != INFO_CTRL_MODE_CFG) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] mode[%d] invalid\n", key, info_ctrl->mode);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* Parameter check */
+ if (!IS_INFO_FRMT_BUF(info_ctrl->frmt) || !INFO_BUF_LEN_VALAID(info_ctrl->len)
+ || (buf_len <= info_ctrl->len)) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] format=%d or len=%d invlaid, buf_len=%d\n",
+ key, info_ctrl->frmt, info_ctrl->len, buf_len);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* Read information */
+ read_bytes = dfd_read_info(info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, info_ctrl->len, buf_tmp);
+ if (read_bytes <= 0) {
+ DBG_DEBUG(DBG_ERROR, "read buf info[key=0x%08llx src=%s frmt=%s fpath=%s addr=0x%x len=%d] fail, rv=%d\n",
+ key, g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], info_ctrl->fpath,
+ info_ctrl->addr, info_ctrl->len, read_bytes);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ /* Data conversion processing */
+ if (pfun) {
+ buf_real_len = buf_len;
+ rv = pfun(buf_tmp, read_bytes, buf, &buf_real_len);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] buf process fail, rv=%d\n", key, rv);
+ return -DFD_RV_DEV_FAIL;
+ }
+ } else {
+ buf_real_len = read_bytes;
+ memcpy(buf, buf_tmp, read_bytes);
+ }
+
+ return buf_real_len;
+}
+
+/**
+ * dfd_2key_info_get_buf - Get buf type information
+ * @key: indicates the search keyword of the configuration item
+ * @buf: Message buf
+ * @buf_len: indicates the buf length, which must be no less than info_ctrl->len
+ * @pfun: Data conversion function pointer
+ *
+ * @returns: <0 fails, others succeed
+ */
+static int dfd_2key_info_get_buf(info_ctrl_t *info_ctrl, uint8_t *buf, int buf_len, info_hwmon_buf_f pfun)
+{
+ int rv;
+ int read_bytes, buf_real_len;
+ uint8_t buf_tmp[INFO_BUF_MAX_LEN];
+ char fpath[INFO_FPATH_MAX_LEN];
+ int coefficient, addend;
+
+ /* Parameter check */
+ if (!IS_INFO_FRMT_BUF(info_ctrl->frmt) || !INFO_BUF_LEN_VALAID(info_ctrl->len)
+ || (buf_len <= info_ctrl->len)) {
+ DBG_DEBUG(DBG_ERROR, "key_path info ctrl format=%d or len=%d invlaid, buf_len=%d\n",
+ info_ctrl->frmt, info_ctrl->len, buf_len);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ mem_clear(buf_tmp, sizeof(buf_tmp));
+ rv = kfile_iterate_dir(info_ctrl->fpath, DFD_HWMON_NAME, buf_tmp, INFO_BUF_MAX_LEN);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "dir patch:%s, can find name %s dir \n",
+ info_ctrl->fpath, DFD_HWMON_NAME);
+ return -DFD_RV_NO_NODE;
+ }
+ mem_clear(fpath, sizeof(fpath));
+ snprintf(fpath, sizeof(fpath), "%s%s/%s",
+ info_ctrl->fpath, buf_tmp, info_ctrl->str_cons);
+ DBG_DEBUG(DBG_VERBOSE, "match ok path: %s\n", fpath);
+
+ mem_clear(buf_tmp, sizeof(buf_tmp));
+ /* Read information */
+ read_bytes = dfd_read_info(info_ctrl->src, fpath, info_ctrl->addr, info_ctrl->len, buf_tmp);
+ if (read_bytes <= 0) {
+ DBG_DEBUG(DBG_ERROR, "read buf info[src: %s frmt: %s fpath: %s addr: 0x%x len: %d] fail, rv=%d\n",
+ g_info_src_str[info_ctrl->src], g_info_src_str[info_ctrl->frmt], fpath,
+ info_ctrl->addr, info_ctrl->len, read_bytes);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ /* Data conversion processing */
+ if (pfun) {
+ buf_real_len = buf_len;
+ coefficient = info_ctrl->int_extra1;
+ addend = info_ctrl->int_extra2;
+ if (coefficient != 0) {
+ rv = pfun(buf_tmp, read_bytes, buf, &buf_real_len, info_ctrl, coefficient, addend);
+ } else {
+ rv = pfun(buf_tmp, read_bytes, buf, &buf_real_len, info_ctrl, 1, addend);
+ }
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl buf process fail, rv=%d\n", rv);
+ return -DFD_RV_DEV_FAIL;
+ }
+ } else {
+ buf_real_len = read_bytes;
+ memcpy(buf, buf_tmp, buf_real_len);
+ }
+ return buf_real_len;
+}
+
+/**
+ * dfd_info_set_int - Set the int type information
+ * @key: Search keyword of the configuration item
+ * @val: int type information
+ *
+ * @returns: 0 succeeds, <0 fails
+ */
+int dfd_info_set_int(uint64_t key, int val)
+{
+ int rv;
+ int write_bytes;
+ uint8_t byte_tmp, bit_mask, val_tmp;
+ info_ctrl_t *info_ctrl;
+ uint8_t *val_buf;
+
+ val_buf = &byte_tmp;
+ /* Entry check */
+ if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key))) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error, key=0x%08llx\n", key);
+ return -DFD_RV_INDEX_INVALID;
+ }
+
+ /* Get the configuration item read and write control variables */
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ /* Non-configuration is not processed */
+ if (info_ctrl->mode != INFO_CTRL_MODE_CFG) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] mode[%d] warnning\n", key, info_ctrl->mode);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* Information conversion */
+ if (IS_INFO_FRMT_BIT(info_ctrl->frmt)) {
+ /* Bit offset check */
+ if (!INFO_BIT_OFFSET_VALID(info_ctrl->bit_offset)) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] bit_offsest[%d] invalid\n",
+ key, info_ctrl->bit_offset);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* Write data value conversion */
+ byte_tmp = (uint8_t)(val & 0xff); /* The minimum 8 bits of data in bit format is valid */
+ byte_tmp <<= info_ctrl->bit_offset; /* The value is shifted to the corresponding bit */
+ if (info_ctrl->pola == INFO_POLA_NEGA) { /* Negative polarity data is reversed */
+ byte_tmp = ~byte_tmp;
+ }
+
+ write_bytes = 1;
+ /* Information valid mask */
+ bit_mask = (~(0xff << info_ctrl->len)) << info_ctrl->bit_offset;
+ if (bit_mask != 0xff) {
+ rv = dfd_read_info(info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, write_bytes,
+ &val_tmp);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR,
+ "read original info[src=%d][fpath=%s][addr=0x%x] fail. rv = %d\n",
+ info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, rv);
+ return -DFD_RV_DEV_FAIL;
+ }
+ val_tmp = (val_tmp & (~bit_mask)) | ((uint8_t)byte_tmp & bit_mask);
+ byte_tmp = val_tmp;
+ }
+ } else if (IS_INFO_FRMT_BYTE(info_ctrl->frmt)) {
+ /* Length check */
+ if (!INFO_INT_LEN_VALAID(info_ctrl->len)) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] len[%d] invalid\n", key, info_ctrl->len);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* XXX There is currently no requirement to set multi-byte int data */
+ write_bytes = 1;
+
+ /* Write data value conversion */
+ byte_tmp = (uint8_t)(val & 0xff);
+
+ /* Information valid mask */
+ bit_mask = 0xff;
+ } else if (IS_INFO_FRMT_NUM_STR(info_ctrl->frmt)) {
+ val_buf = info_ctrl->str_cons;
+ write_bytes = strlen(info_ctrl->str_cons);
+ if (write_bytes <= 0) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] write num_str: fpath: %s, len[%d] invalid\n",
+ key, info_ctrl->fpath, write_bytes);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ bit_mask = 0xff;
+ DBG_DEBUG(DBG_VERBOSE, "info ctrl[key=0x%08llx], write num_str: fpath: %s, write val: %s, len: %d\n",
+ key, info_ctrl->fpath, val_buf, write_bytes);
+ } else if (IS_INFO_FRMT_NUM_BUF(info_ctrl->frmt)) {
+ /* Length check */
+ if (!INFO_INT_LEN_VALAID(info_ctrl->len)) {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] len[%d] invalid\n", key, info_ctrl->len);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* num is converted before buf is set. XXX does not need to set multi-byte int data */
+ write_bytes = 1;
+
+ /* Write data value conversion */
+ byte_tmp = (uint8_t)(val & 0xff);
+
+ /* Information valid mask */
+ bit_mask = 0xff;
+ } else {
+ DBG_DEBUG(DBG_ERROR, "info ctrl[key=0x%08llx] format[%d] error\n", key, info_ctrl->frmt);
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ /* Write message */
+ rv = dfd_write_info(info_ctrl->src, info_ctrl->fpath, info_ctrl->addr, write_bytes,
+ val_buf, bit_mask);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "write int info[src=%s frmt=%s fpath=%s addr=0x%x len=%d val=%d] fail, rv=%d\n",
+ g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], info_ctrl->fpath,
+ info_ctrl->addr, info_ctrl->len, val, rv);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "write int info[src=%s frmt=%s pola=%s fpath=%s addr=0x%x len=%d bit_offset=%d val=%d] success\n",
+ g_info_src_str[info_ctrl->src], g_info_frmt_str[info_ctrl->frmt], g_info_pola_str[info_ctrl->pola],
+ info_ctrl->fpath, info_ctrl->addr, info_ctrl->len, info_ctrl->bit_offset, val);
+ return DFD_RV_OK;
+}
+
+static long dfd_info_reg2data_linear(uint64_t key, int data)
+{
+ s16 exponent;
+ s32 mantissa;
+ long val;
+ info_ctrl_t *info_ctrl;
+
+ /* Get the configuration item read and write control variables */
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ switch (info_ctrl->int_extra1) {
+ case LINEAR11:
+ exponent = ((s16)data) >> 11;
+ mantissa = ((s16)((data & 0x7ff) << 5)) >> 5;
+ val = mantissa;
+ val = val * 1000L;
+ break;
+ case LINEAR16:
+ break;
+ default:
+ break;
+ }
+
+ if (DFD_CFG_ITEM_ID(key) == DFD_CFG_ITEM_HWMON_POWER) {
+ val = val * 1000L;
+ }
+
+ if (exponent >= 0) {
+ val <<= exponent;
+ } else {
+ val >>= -exponent;
+ }
+
+ return val;
+}
+
+static long dfd_info_reg2data_tmp464(uint64_t key, int data)
+{
+ s16 tmp_val;
+ long val;
+
+ DBG_DEBUG(DBG_VERBOSE, "reg2data_tmp464, data=%d\n", data);
+
+ /* Positive number:data/8*0.0625 */
+ if (data >= 0) {
+ val = data*625/80;
+ /* Negative number: The first bit is the sign bit and the rest is inverted +1 */
+ } else {
+ tmp_val = ~(data & 0x7ff) + 1;
+ val = tmp_val*625/80;
+ }
+
+ return val;
+}
+
+static long dfd_info_reg2data_mac_th5(uint64_t key, int data)
+{
+ int tmp_val;
+ long val;
+
+ DBG_DEBUG(DBG_VERBOSE, "reg2data_mac_th5, data=0x%d\n", data);
+
+ tmp_val = data >> 4;
+ val = 476359 - (((tmp_val - 2) * 317704) / 2000);
+
+ DBG_DEBUG(DBG_VERBOSE, "reg2data_mac_th5, val=0x%ld\n", val);
+ return val;
+}
+
+static long dfd_info_reg2data_mac_th4(uint64_t key, int data)
+{
+ int tmp_val;
+ int val;
+
+ DBG_DEBUG(DBG_VERBOSE, "reg2data_mac_th4, data=%d\n", data);
+
+ tmp_val = data >> 4;
+ val = 356070 - (((tmp_val - 2) * 237340) / 2000);
+
+ DBG_DEBUG(DBG_VERBOSE, "reg2data_mac_th4, val=%d\n", val);
+ return val;
+}
+
+
+static int dfd_info_get_cpld_voltage(uint64_t key, uint32_t *value)
+{
+ int rv;
+ uint32_t vol_ref_tmp, vol_ref;
+ uint32_t vol_curr_tmp, vol_curr;
+ info_ctrl_t *info_ctrl;
+ info_ctrl_t info_ctrl_tmp;
+ uint32_t vol_coefficient;
+
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ vol_coefficient = (uint32_t)info_ctrl->int_extra2;
+
+ rv = dfd_get_info_value(info_ctrl, &vol_curr_tmp, NULL);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get cpld current voltage error, addr:0x%x, rv = %d\n", info_ctrl->addr, rv);
+ return rv;
+ }
+ if (info_ctrl->int_extra3 == CPLD_VOLATGE_VALUE_MODE2) {
+ vol_curr_tmp = DFD_GET_CPLD_VOLATGE_CODE_VALUE2(vol_curr_tmp);
+ vol_curr = DFD_GET_CPLD_VOLATGE_REAL_VALUE2(vol_curr_tmp, info_ctrl->int_extra2);
+ DBG_DEBUG(DBG_VERBOSE, "vol_curr_tmp = 0x%x, vol_curr = 0x%x, is same.\n", vol_curr_tmp, vol_curr);
+ } else {
+ vol_curr_tmp = DFD_GET_CPLD_VOLATGE_CODE_VALUE(vol_curr_tmp);
+ if (info_ctrl->addr == info_ctrl->int_extra1) {
+ vol_curr = DFD_GET_CPLD_VOLATGE_REAL_VALUE(vol_curr_tmp, vol_coefficient);
+ DBG_DEBUG(DBG_VERBOSE, "current voltage is reference voltage, vol_curr_tmp: 0x%x, coefficient: %u, vol_curr: %u\n",
+ vol_curr_tmp, vol_coefficient, vol_curr);
+ } else {
+ memcpy(&info_ctrl_tmp, info_ctrl, sizeof(info_ctrl_t));
+ info_ctrl_tmp.addr = info_ctrl->int_extra1;
+ rv = dfd_get_info_value(&info_ctrl_tmp, &vol_ref_tmp, NULL);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get cpld reference voltage error, addr: 0x%x, rv: %d\n", info_ctrl_tmp.addr, rv);
+ return rv;
+ }
+ vol_ref = DFD_GET_CPLD_VOLATGE_CODE_VALUE(vol_ref_tmp);
+ DBG_DEBUG(DBG_VERBOSE, "vol_ref_tmp: 0x%x, vol_ref: 0x%x\n", vol_ref_tmp, vol_ref);
+ vol_curr = (vol_curr_tmp * vol_coefficient) / vol_ref;
+ DBG_DEBUG(DBG_VERBOSE, "vol_curr_tmp: 0x%x, vol_ref: 0x%x, coefficient: %u, vol_curr: %u\n",
+ vol_curr_tmp, vol_ref, vol_coefficient, vol_curr);
+ }
+ }
+ *value = vol_curr;
+ return DFD_RV_OK;
+}
+
+static int dfd_info_get_cpld_temperature(uint64_t key, int *value)
+{
+ int rv;
+ int temp_reg;
+ info_ctrl_t *info_ctrl;
+ long val;
+
+ /* Get the configuration item read and write control variables */
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_WARN, "get info ctrl fail, key=0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ /* Read the temperature value */
+ rv = dfd_info_get_int(key, &temp_reg, NULL);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get cpld current temperature error, addr:0x%x, rv =%d\n", info_ctrl->addr, rv);
+ return rv;
+ }
+ DBG_DEBUG(DBG_VERBOSE, "get cpld temp:0x%08x, extra1 0x%x\n", temp_reg, info_ctrl->int_extra1);
+
+ switch (info_ctrl->int_extra1) {
+ case LINEAR11:
+ val = dfd_info_reg2data_linear(key, temp_reg);
+ break;
+ case TMP464:
+ val = dfd_info_reg2data_tmp464(key, temp_reg);
+ break;
+ case MAC_TH5:
+ val = dfd_info_reg2data_mac_th5(key, temp_reg);
+ break;
+ case MAC_TH4:
+ val = dfd_info_reg2data_mac_th4(key, temp_reg);
+ break;
+ default:
+ val = temp_reg;
+ break;
+ }
+
+ if ((val / 1000 < VALID_MAC_TEMP_MIN) || (val / 1000 > VALID_MAC_TEMP_MAX)) {
+ DBG_DEBUG(DBG_ERROR, "mac temp invalid, temp = %ld\n", val);
+ val = MAC_TEMP_INVALID;
+ }
+ DBG_DEBUG(DBG_VERBOSE, "calc temp:%ld \n", val);
+ *value = val;
+
+ return DFD_RV_OK;
+}
+
+static int dfd_info_get_sensor_value(uint64_t key, uint8_t *buf, int buf_len, info_hwmon_buf_f pfun)
+{
+ int rv, buf_real_len;
+ uint32_t value;
+ int temp_value;
+ uint8_t buf_tmp[INFO_BUF_MAX_LEN];
+ info_ctrl_t *info_ctrl;
+
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_ERROR, "get info ctrl fail, key=0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ if (DFD_CFG_ITEM_ID(key) == DFD_CFG_ITEM_HWMON_IN && info_ctrl->src == INFO_SRC_CPLD) {
+ rv = dfd_info_get_cpld_voltage(key, &value);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get cpld voltage failed.key=0x%08llx, rv:%d\n", key, rv);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ DBG_DEBUG(DBG_VERBOSE, "get cpld voltage ok, value:%u\n", value);
+ mem_clear(buf_tmp, sizeof(buf_tmp));
+ snprintf(buf_tmp, sizeof(buf_tmp), "%u\n", value);
+ buf_real_len = strlen(buf_tmp);
+ if (buf_len <= buf_real_len) {
+ DBG_DEBUG(DBG_ERROR, "length not enough.buf_len:%d,need length:%d\n", buf_len, buf_real_len);
+ return -DFD_RV_DEV_FAIL;
+ }
+ if (pfun) {
+ buf_real_len = buf_len;
+ rv = pfun(buf_tmp, strlen(buf_tmp), buf, &buf_real_len, info_ctrl, 1, 0);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "deal date error.org value:%s, buf_len:%d, rv=%d\n",
+ buf_tmp, buf_len, rv);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ } else {
+ memcpy(buf, buf_tmp, buf_real_len);
+ }
+ return buf_real_len;
+ } else if (DFD_CFG_ITEM_ID(key) == DFD_CFG_ITEM_HWMON_TEMP && info_ctrl->src == INFO_SRC_CPLD) {
+ rv = dfd_info_get_cpld_temperature(key, &temp_value);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get cpld temperature failed.key=0x%08llx, rv:%d\n", key, rv);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ DBG_DEBUG(DBG_VERBOSE, "get cpld temperature ok, value:%d buf_len %d\n", temp_value, buf_len);
+ mem_clear(buf_tmp, sizeof(buf_tmp));
+ snprintf(buf_tmp, sizeof(buf_tmp), "%d\n", temp_value);
+ buf_real_len = strlen(buf_tmp);
+ if (buf_len <= buf_real_len) {
+ DBG_DEBUG(DBG_ERROR, "length not enough.buf_len:%d,need length:%d\n", buf_len, buf_real_len);
+ return -DFD_RV_DEV_FAIL;
+ }
+ DBG_DEBUG(DBG_VERBOSE, "buf_real_len %d\n", buf_real_len);
+ memcpy(buf, buf_tmp, buf_real_len);
+ return buf_real_len;
+ }
+
+ DBG_DEBUG(DBG_ERROR, "not support mode. key:0x%08llx\n", key);
+ return -DFD_RV_MODE_NOTSUPPORT;
+}
+
+/**
+ * dfd_info_get_sensor - Get sensors
+ * @key: HWMON Configures the key
+ * @buf:Result storage
+ * @buf_len: buf Length
+ *
+ * @returns: <0 Failure, other success
+ */
+int dfd_info_get_sensor(uint64_t key, char *buf, int buf_len, info_hwmon_buf_f pfun)
+{
+ info_ctrl_t *key_info_ctrl;
+ int rv;
+
+ /* Entry check */
+ if (!DFD_CFG_ITEM_IS_INFO_CTRL(DFD_CFG_ITEM_ID(key)) ||
+ (buf == NULL) || buf_len <= 0) {
+ DBG_DEBUG(DBG_ERROR, "input arguments error, key: 0x%08llx, buf_len: %d\n",
+ key, buf_len);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ mem_clear(buf, buf_len);
+ /* Get the configuration item read and write control variables */
+ key_info_ctrl = dfd_ko_cfg_get_item(key);
+ if (key_info_ctrl == NULL) {
+ DBG_DEBUG(DBG_VERBOSE, "can't find dfd config, key: 0x%08llx\n", key);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ /* String type */
+ if (key_info_ctrl->mode == INFO_CTRL_MODE_SRT_CONS) {
+ snprintf(buf, buf_len, "%s\n", key_info_ctrl->str_cons);
+ DBG_DEBUG(DBG_VERBOSE, "get sensor value through string config, key: 0x%08llx, value: %s\n", key, buf);
+ return strlen(buf);
+ }
+ /* int constant type */
+ if (key_info_ctrl->mode == INFO_CTRL_MODE_CONS) {
+ snprintf(buf, buf_len, "%d\n", key_info_ctrl->int_cons);
+ DBG_DEBUG(DBG_VERBOSE, "get sensor value through int config, key: 0x%08llx, value: %d\n", key, key_info_ctrl->int_cons);
+ return strlen(buf);
+ }
+
+ /* Read from the hwmon file */
+ if (key_info_ctrl->mode == INFO_CTRL_MODE_CFG && key_info_ctrl->src == INFO_SRC_FILE) {
+ if (strstr(key_info_ctrl->fpath, "hwmon") != NULL) {
+ DBG_DEBUG(DBG_VERBOSE, "get sensor value through hwmon, key: 0x%08llx\n", key);
+ rv = dfd_2key_info_get_buf(key_info_ctrl, buf, buf_len, pfun);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_VERBOSE, "get sensor value through hwmon failed, key: 0x%08llx, rv: %d\n", key, rv);
+ }
+ return rv;
+ } else {
+ DBG_DEBUG(DBG_VERBOSE, "get sensor value, key:0x%08llx\n", key);
+ rv = dfd_info_get_buf(key, buf, buf_len, NULL);
+ if (rv < 0) {
+ DBG_DEBUG(DBG_VERBOSE, "get sensor value failed, key:0x%08llx, rv:%d\n", key, rv);
+ }
+ return rv;
+ }
+ }
+ rv = dfd_info_get_sensor_value(key, buf, buf_len, pfun);
+ if ( rv < 0) {
+ DBG_DEBUG(DBG_ERROR, "get sensor value failed, key: 0x%08llx, rv: %d\n", key, rv);
+ }
+ return rv;
+}
+
+/**
+ * @buf:Input and result store
+ *
+ */
+void dfd_info_del_no_print_string(char *buf)
+{
+ int i, len;
+
+ len = strlen(buf);
+ /* Culling noncharacter */
+ for (i = 0; i < len; i++) {
+ if ((buf[i] < 0x21) || (buf[i] > 0x7E)) {
+ buf[i] = '\0';
+ break;
+ }
+ }
+ return;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_listnode.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_listnode.c
new file mode 100644
index 000000000000..888cfe8b05f2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_cfg_listnode.c
@@ -0,0 +1,133 @@
+/*
+ * An dfd_cfg_listnode driver for cfg of listnode devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+
+#include "dfd_cfg_listnode.h"
+
+/**
+ * Find node
+ * @root: Root node pointer
+ * @key: Node index value
+ *
+ * @return : Node data pointer, NULL failed
+ */
+void *lnode_find_node(lnode_root_t *root, uint64_t key)
+{
+ lnode_node_t *lnode;
+
+ if (root == NULL) {
+ return NULL;
+ }
+
+ /* Traversal query */
+ list_for_each_entry(lnode, &(root->root), lst) {
+ if (lnode->key == key) {
+ return lnode->data;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Insert node
+ * @root: Root node pointer
+ * @key: Node index value
+ * @data: data
+ *
+ * @return : 0-- success, other failures
+ */
+int lnode_insert_node(lnode_root_t *root, uint64_t key, void *data)
+{
+ lnode_node_t *lnode;
+ void *data_tmp;
+
+ if ((root == NULL) || (data == NULL)) {
+ return LNODE_RV_INPUT_ERR;
+ }
+
+ /* Check whether the node exists */
+ data_tmp = lnode_find_node(root, key);
+ if (data_tmp != NULL) {
+ return LNODE_RV_NODE_EXIST;
+ }
+
+ /* Node memory request */
+ lnode = kmalloc(sizeof(lnode_node_t), GFP_KERNEL);
+ if (lnode == NULL) {
+ return LNODE_RV_NOMEM;
+ }
+
+ /* Add to list */
+ lnode->key = key;
+ lnode->data = data;
+ list_add_tail(&(lnode->lst), &(root->root));
+
+ return LNODE_RV_OK;
+}
+
+/**
+ * Example Initialize the root node
+ * @root: Root node pointer
+ *
+ * @return : 0 Succeeded, others failed
+ */
+int lnode_init_root(lnode_root_t *root)
+{
+ if (root == NULL) {
+ return LNODE_RV_INPUT_ERR;
+ }
+
+ INIT_LIST_HEAD(&(root->root));
+
+ return LNODE_RV_OK;
+}
+
+/**
+ * Free linked list
+ * @root: Root node pointer
+ *
+ * @return : void
+ */
+void lnode_free_list(lnode_root_t *root)
+{
+ lnode_node_t *lnode, *lnode_next;
+
+ if (root == NULL) {
+ return;
+ }
+
+ /* Iterate to delete the linked list */
+ list_for_each_entry_safe(lnode, lnode_next, &(root->root), lst) {
+ if (lnode->data) {
+ kfree(lnode->data);
+ lnode->data = NULL;
+ lnode->key = 0;
+ }
+ list_del(&lnode->lst);
+ kfree(lnode);
+ lnode = NULL;
+ }
+
+ return;
+
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_frueeprom.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_frueeprom.c
new file mode 100644
index 000000000000..ded8eb8a8db8
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_frueeprom.c
@@ -0,0 +1,534 @@
+/*
+ * An dfd_frueeprom driver for frueeprom devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "dfd_frueeprom.h"
+#include "dfd_cfg_adapter.h"
+#include "wb_module.h"
+
+int g_dfd_fru_dbg_level = 0;
+module_param(g_dfd_fru_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/**
+ * Takes the pointer to stream of bytes and length
+ * and returns the 8 bit checksum
+ * This algo is per IPMI V2.0 spec
+ */
+static unsigned char ipmi_calculate_crc(const unsigned char *data, size_t len)
+{
+ char crc = 0;
+ size_t byte = 0;
+
+ for (byte = 0; byte < len; byte++) {
+ crc += *data++;
+ }
+
+ return(-crc);
+}
+
+/* Validates the data for crc and mandatory fields */
+static int ipmi_verify_fru_data(const uint8_t *data, const size_t len)
+{
+ uint8_t checksum = 0;
+ int rc = -DFD_RV_TYPE_ERR;
+
+ /* Validate for first byte to always have a value of [1] */
+ if (data[0] != IPMI_FRU_HDR_BYTE_ZERO) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid entry:[%d] in byte-0\n",data[0]);
+ return rc;
+ } else {
+ DBG_FRU_DEBUG(DBG_VERBOSE, "SUCCESS: Validated [0x%X] in entry_1 of fru_data\n",data[0]);
+ }
+
+ /* See if the calculated CRC matches with the embedded one.
+ * CRC to be calculated on all except the last one that is CRC itself.*/
+ checksum = ipmi_calculate_crc(data, len - 1);
+ if (checksum != data[len-1]) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Checksum mismatch."
+ " Calculated:[0x%X], Embedded:[0x%X]\n",
+ checksum, data[len - 1]);
+ return rc;
+ } else {
+ DBG_FRU_DEBUG(DBG_VERBOSE, "SUCCESS: Checksum matches:[0x%X]\n",checksum);
+ }
+
+ return 0;
+}
+
+/* private method to parse type/length */
+static int ipmi_parse_type_length (const void *areabuf,
+ unsigned int areabuflen,
+ unsigned int current_area_offset,
+ uint8_t *number_of_data_bytes,
+ ipmi_fru_field_t *field)
+{
+ const uint8_t *areabufptr = (const uint8_t*) areabuf;
+ uint8_t type_length;
+ uint8_t type_code;
+
+ type_length = areabufptr[current_area_offset];
+
+ /* ipmi workaround
+ *
+ * dell p weredge r610
+ *
+ * my reading of the fru spec is that all non-custom fields are
+ * required to be listed by the vendor. however, on this
+ * motherboard, some areas list this, indicating that there is
+ * no more data to be parsed. so now, for "required" fields, i
+ * check to see if the type-length field is a sentinel before
+ * calling this function.
+ */
+
+ type_code = (type_length & IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK) >> IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT;
+ (*number_of_data_bytes) = type_length & IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK;
+
+ /* special case: this shouldn't be a length of 0x01 (see type/length
+ * byte format in fru information storage definition).
+ */
+ DBG_FRU_DEBUG(DBG_VERBOSE, "areabuflen:%d, current_area_offset:0x%x, type_code:0x%x, number_of_data_bytes:%d\n",
+ areabuflen, current_area_offset, type_code, *number_of_data_bytes);
+#if 0
+ if (type_code == IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE
+ && (*number_of_data_bytes) == 0x01) {
+ DBG_FRU_DEBUG(DBG_ERROR, "fru type length error.value:0x%x\n", type_length);
+ return (-1);
+ }
+#endif
+ if ((current_area_offset + 1 + (*number_of_data_bytes)) > areabuflen) {
+ DBG_FRU_DEBUG(DBG_ERROR, "buf length error. current_area_offset:0x%x, need length:%d, total length:0x%x\n",
+ current_area_offset, *number_of_data_bytes, areabuflen);
+ return (-1);
+ }
+
+ if (field) {
+ mem_clear (field->type_length_field, IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX);
+ memcpy (field->type_length_field, &areabufptr[current_area_offset + 1], *number_of_data_bytes);
+ DBG_FRU_DEBUG(DBG_VERBOSE, "fru parse ok. value:%s\n", field->type_length_field);
+ field->type_length_field_length = *number_of_data_bytes;
+ }
+
+ return (0);
+}
+
+static int ipmi_fru_product_info_area(const void *areabuf,
+ unsigned int areabuflen, ipmi_product_info_t *ipmi_product_info)
+{
+ const uint8_t *areabufptr = (const uint8_t*) areabuf;
+ unsigned int area_offset = 2;
+ uint8_t number_of_data_bytes;
+ int rv;
+ ipmi_fru_field_t **ipmi_fru_field_point;
+ int ipmi_fru_field_len, i;
+
+ if (!areabuf || !areabuflen || !ipmi_product_info) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid Parameter.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Verify the crc and size */
+ rv = ipmi_verify_fru_data(areabuf, areabuflen);
+ if (rv < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Failed to validate fru product info data\n");
+ return rv;
+ }
+
+ ipmi_fru_field_len = (sizeof(ipmi_product_info_t) - sizeof(uint8_t *)) /(sizeof(ipmi_fru_field_t *));
+
+ if (ipmi_product_info->language_code) {
+ (*ipmi_product_info->language_code) = areabufptr[area_offset];
+ }
+ area_offset++;
+ ipmi_fru_field_point = (ipmi_fru_field_t **)((uint8_t *)ipmi_product_info + sizeof(uint8_t *));
+ for (i = 0; i < ipmi_fru_field_len; i++) {
+ if (*ipmi_fru_field_point) {
+ mem_clear(*ipmi_fru_field_point, sizeof(ipmi_fru_field_t));
+ }
+
+ if (((areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE) && (i >= IPMI_FRU_PRODUCT_AREA_MIN_LEN))
+ || (area_offset == areabuflen - 1)) {
+ rv = 0;
+ break;
+ }
+
+ rv = ipmi_parse_type_length(areabufptr, areabuflen, area_offset, &number_of_data_bytes, *ipmi_fru_field_point);
+ if (rv < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "[%d] _parse_type_length area_offset[%d] rv=%d \n", i, area_offset, rv);
+ break;
+ }
+
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+ ipmi_fru_field_point++;
+ }
+
+ return (rv);
+}
+
+static int ipmi_fru_board_info_area(const void *areabuf,
+ unsigned int areabuflen, ipmi_board_info_t *ipmi_board_info)
+{
+ const uint8_t *areabufptr = (const uint8_t*) areabuf;
+ unsigned int area_offset = 2;
+ uint8_t number_of_data_bytes;
+ int rv;
+ ipmi_fru_field_t **ipmi_fru_field_point;
+ int ipmi_fru_field_len, i;
+
+ if (!areabuf || !areabuflen || !ipmi_board_info) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid Parameter.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Verify the crc and size */
+ rv = ipmi_verify_fru_data(areabuf, areabuflen);
+ if (rv < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Failed to validate fru product info data\n");
+ return rv;
+ }
+
+ ipmi_fru_field_len = (sizeof(ipmi_board_info_t) - sizeof(uint8_t *) - sizeof(uint8_t *)) /(sizeof(ipmi_fru_field_t *));
+
+ if (ipmi_board_info->language_code) {
+ (*ipmi_board_info->language_code) = areabufptr[area_offset];
+ }
+ area_offset++;
+
+ if (ipmi_board_info->mfg_time) {
+ memcpy(ipmi_board_info->mfg_time, &areabufptr[area_offset], IPMI_FRU_BOARD_INFO_MFG_TIME_LENGTH);
+ }
+ area_offset += IPMI_FRU_BOARD_INFO_MFG_TIME_LENGTH;
+ ipmi_fru_field_point = (ipmi_fru_field_t **)((uint8_t *)ipmi_board_info + sizeof(uint8_t *) + sizeof(uint8_t *));
+ for (i = 0; i < ipmi_fru_field_len; i++) {
+ if (*ipmi_fru_field_point) {
+ mem_clear(*ipmi_fru_field_point, sizeof(ipmi_fru_field_t));
+ }
+
+ if (((areabufptr[area_offset] == IPMI_FRU_SENTINEL_VALUE) && (i >= IPMI_FRU_BOARD_AREA_MIN_LEN))
+ || (area_offset == areabuflen - 1)) {
+ rv = 0;
+ break;
+ }
+
+ rv = ipmi_parse_type_length(areabufptr, areabuflen, area_offset, &number_of_data_bytes, *ipmi_fru_field_point);
+ if (rv < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "[%d] _parse_type_length area_offset[%d] rv=%d \n", i, area_offset, rv);
+ break;
+ }
+
+ area_offset += 1; /* type/length byte */
+ area_offset += number_of_data_bytes;
+ ipmi_fru_field_point++;
+ }
+
+ return (rv);
+}
+
+/**
+ * Validates the fru data per ipmi common header constructs.
+ * Returns with updated common_hdr and also file_size
+ */
+static int ipmi_validate_common_hdr(const uint8_t *fru_data, const size_t data_len)
+{
+ int rc = -1;
+
+ uint8_t common_hdr[sizeof(fru_common_header_t)] = {0};
+ if (data_len >= sizeof(common_hdr)) {
+ memcpy(common_hdr, fru_data, sizeof(common_hdr));
+ } else {
+ DBG_FRU_DEBUG(DBG_ERROR, "Incomplete fru data file. Size:[%zd]\n", data_len);
+ return rc;
+ }
+
+ /* Verify the crc and size */
+ rc = ipmi_verify_fru_data(common_hdr, sizeof(common_hdr));
+ if (rc < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Failed to validate common header\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+/* Header information acquisition */
+static int dfd_get_frue2prom_info(int bus, int dev_addr, fru_common_header_t *info, const char *sysfs_name)
+{
+ int ret;
+ uint8_t fru_common_header_info[sizeof(fru_common_header_t)];
+
+ if (info == NULL) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ ret = dfd_ko_i2c_read(bus, dev_addr, 0, (uint8_t *)info, sizeof(fru_common_header_t), sysfs_name);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Read eeprom head info error(bus: %d, addr: 0x%02x).\n", bus, dev_addr);
+ return ret;
+ }
+
+ memcpy(fru_common_header_info, (uint8_t *)info, sizeof(fru_common_header_t));
+
+ if (ipmi_validate_common_hdr(fru_common_header_info, sizeof(fru_common_header_t)) != 0) {
+ return -DFD_RV_TYPE_ERR;
+ }
+
+ return DFD_RV_OK;
+}
+
+static int dfd_set_fru_product_info(ipmi_product_info_t *ipmi_product_info, ipmi_fru_field_t *vpd_info, int type)
+{
+ int ret;
+ ret = DFD_RV_OK;
+ if (ipmi_product_info == NULL || vpd_info == NULL) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear((uint8_t *)ipmi_product_info, sizeof(ipmi_product_info_t));
+ switch (type) {
+ case DFD_DEV_INFO_TYPE_SN:
+ ipmi_product_info->product_serial_number = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_NAME:
+ ipmi_product_info->product_name = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_DEV_TYPE:
+ ipmi_product_info->product_type_fields = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_HW_INFO:
+ ipmi_product_info->product_version = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_VENDOR:
+ ipmi_product_info->product_manufacturer_name = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_PART_NUMBER:
+ ipmi_product_info->product_part_model_number = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_ASSET_TAG:
+ ipmi_product_info->product_asset_tag = vpd_info;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+static int dfd_set_fru_board_info(ipmi_board_info_t *ipmi_board_info, ipmi_fru_field_t *vpd_info, int type)
+{
+ int ret;
+ ret = DFD_RV_OK;
+ if (ipmi_board_info == NULL || vpd_info == NULL) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear((uint8_t *)ipmi_board_info, sizeof(ipmi_board_info_t));
+ switch (type) {
+ case DFD_DEV_INFO_TYPE_SN:
+ ipmi_board_info->board_serial_number = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_NAME:
+ ipmi_board_info->board_product_name = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_HW_INFO:
+ ipmi_board_info->board_custom_fields = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_PART_NUMBER:
+ ipmi_board_info->board_part_number = vpd_info;
+ break;
+ case DFD_DEV_INFO_TYPE_VENDOR:
+ ipmi_board_info->board_manufacturer = vpd_info;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * dfd_get_fru_data - Obtain product area FRU information
+ * @bus:FRU E2 bus number
+ * @dev_addr:FRU E2 Device address
+ * @type 2: Product name, 3: product serial number 5: hardware version number 6: product ID
+ * @buf: Data is stored in buf
+ * @buf_len:buf length
+ * @sysfs_name:sysfs attribute name
+ * @returns:0 success, negative value: failed
+ */
+int dfd_get_fru_data(int bus, int dev_addr, int type, uint8_t *buf, uint32_t buf_len, const char *sysfs_name)
+{
+ fru_common_header_t info;
+ uint8_t *fru_data;
+ int ret;
+ uint8_t fru_len;
+ ipmi_product_info_t ipmi_product_info;
+ ipmi_fru_field_t vpd_info;
+ int product_offset;
+ int fru_len_tmp;
+
+ if (buf == NULL || buf_len <= 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ DBG_FRU_DEBUG(DBG_VERBOSE, "Read fru eeprom (bus: %d, addr: 0x%02x, type:%d, buf: %p, len: %d).\n",
+ bus, dev_addr, type, buf, buf_len);
+
+ ret = dfd_get_frue2prom_info(bus, dev_addr, &info, sysfs_name);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Read eeprom info head error(bus: %d, addr: 0x%02x, buf: %p, len: %d).\n",
+ bus, dev_addr, buf, buf_len);
+ return ret;
+ }
+
+ product_offset = info.product_offset * IPMI_EIGHT_BYTES;
+ ret = dfd_ko_i2c_read(bus, dev_addr, product_offset + 1, &fru_len, 1, sysfs_name);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "read eeprom info product_offset(bus: %d, addr: 0x%02x, product offset:%d).\n",
+ bus, dev_addr, info.product_offset);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ fru_len_tmp = fru_len * IPMI_EIGHT_BYTES;
+ fru_data = (uint8_t *)kmalloc(sizeof(uint8_t) * fru_len_tmp, GFP_KERNEL);
+ if (fru_data == NULL) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Allocate buffer(len:%d) error!\n", fru_len_tmp);
+ return -DFD_RV_NO_MEMORY;
+ }
+
+ ret = dfd_ko_i2c_read(bus, dev_addr, product_offset, fru_data, fru_len_tmp, sysfs_name);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Get FRU data error.\n");
+ kfree(fru_data);
+ return ret;
+ }
+
+ mem_clear((uint8_t *)&vpd_info, sizeof(ipmi_fru_field_t));
+ ret = dfd_set_fru_product_info(&ipmi_product_info, &vpd_info, type);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Not support to get info: %d.\n", type);
+ kfree(fru_data);
+ return ret;
+ }
+
+ ret = ipmi_fru_product_info_area(fru_data, fru_len_tmp, &ipmi_product_info);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "analysis FRU product info error.\n");
+ kfree(fru_data);
+ return ret;
+ }
+
+ kfree(fru_data);
+
+ buf_len = buf_len < vpd_info.type_length_field_length ? buf_len : vpd_info.type_length_field_length;
+ memcpy(buf, (uint8_t *)&vpd_info, buf_len);
+
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fru_board_data - Obtain the FRU information of the board area
+ * @bus:FRU E2 bus number
+ * @dev_addr:FRU E2 Device address
+ * @type: 2: Product name, 3: product serial number 5: hardware version number
+ * @buf:Data is stored in buf
+ * @buf_len:buf length
+ * @sysfs_name:sysfs attribute name
+ * @returns: 0 success, negative value: failed
+ */
+int dfd_get_fru_board_data(int bus, int dev_addr, int type, uint8_t *buf, uint32_t buf_len, const char *sysfs_name)
+{
+ fru_common_header_t info;
+ uint8_t *fru_data;
+ int ret;
+ uint8_t fru_len;
+ ipmi_board_info_t ipmi_board_info;
+ ipmi_fru_field_t vpd_info;
+ int board_offset;
+ int fru_len_tmp;
+
+ if (buf == NULL || buf_len <= 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Invalid parameter!\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ DBG_FRU_DEBUG(DBG_VERBOSE, "Read fru eeprom (bus: %d, addr: 0x%02x, type:%d, buf: %p, len: %d).\n",
+ bus, dev_addr, type, buf, buf_len);
+
+ ret = dfd_get_frue2prom_info(bus, dev_addr, &info, sysfs_name);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Read eeprom info head error(bus: %d, addr: 0x%02x, buf: %p, len: %d).\n",
+ bus, dev_addr, buf, buf_len);
+ return ret;
+ }
+
+ board_offset = info.board_offset * IPMI_EIGHT_BYTES;
+ ret = dfd_ko_i2c_read(bus, dev_addr, board_offset + 1, &fru_len, 1, sysfs_name);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "read eeprom info product_offset(bus: %d, addr: 0x%02x, product offset:%d).\n",
+ bus, dev_addr, info.board_offset);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ fru_len_tmp = fru_len * IPMI_EIGHT_BYTES;
+ fru_data = (uint8_t *)kmalloc(sizeof(uint8_t) * fru_len_tmp, GFP_KERNEL);
+ if (fru_data == NULL) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Allocate buffer(len:%d) error!\n", fru_len_tmp);
+ return -DFD_RV_NO_MEMORY;
+ }
+
+ ret = dfd_ko_i2c_read(bus, dev_addr, board_offset, fru_data, fru_len_tmp, sysfs_name);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Get FRU data error.\n");
+ kfree(fru_data);
+ return ret;
+ }
+
+ mem_clear((uint8_t *)&vpd_info, sizeof(ipmi_fru_field_t));
+ ret = dfd_set_fru_board_info(&ipmi_board_info, &vpd_info, type);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "Not support to get info: %d.\n", type);
+ kfree(fru_data);
+ return ret;
+ }
+
+ ret = ipmi_fru_board_info_area(fru_data, fru_len_tmp, &ipmi_board_info);
+ if (ret < 0) {
+ DBG_FRU_DEBUG(DBG_ERROR, "analysis FRU product info error.\n");
+ kfree(fru_data);
+ return ret;
+ }
+
+ kfree(fru_data);
+
+ buf_len = buf_len < vpd_info.type_length_field_length ? buf_len : vpd_info.type_length_field_length;
+ memcpy(buf, (uint8_t *)&vpd_info, buf_len);
+
+ return DFD_RV_OK;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_tlveeprom.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_tlveeprom.c
new file mode 100644
index 000000000000..3011aa2cac04
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/cfg/dfd_tlveeprom.c
@@ -0,0 +1,469 @@
+/*
+ * An dfd_tlveeprom driver for tlveeprom devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "dfd_tlveeprom.h"
+#include "wb_module.h"
+
+#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)
+
+/* using in is_valid_tlvinfo_header */
+static uint32_t g_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"},
+};
+
+#define TLV_CODE_NUM (sizeof(tlv_code_list) / sizeof(tlv_code_list[0]))
+
+const unsigned long g_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 = g_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 = g_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;
+ uint32_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:
+ 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;
+ 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 %02X", value, tlv->value[i]);
+ }
+ break;
+ 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(uint8_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(uint8_t *eeprom, uint8_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(uint8_t *eeprom, uint8_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(uint8_t *eeprom, uint32_t size)
+{
+ unsigned int i;
+ bool ret;
+ tlvinfo_header_t *eeprom_hdr;
+ tlv_decode_value_t decode_value;
+ int j;
+
+ eeprom_hdr = (tlvinfo_header_t *) eeprom;
+ g_eeprom_size = size; /* eeprom real size */
+
+ if (!is_valid_tlvinfo_header(eeprom_hdr)) {
+ DBG_DEBUG(DBG_ERROR, "Failed to check tlv header.\n");
+ return -1;
+ }
+
+ if (!is_checksum_valid(eeprom)) {
+ DBG_DEBUG(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_DEBUG(DBG_ERROR, "No found type: %s\n", tlv_code_list[i].m_name);
+ continue;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "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(DBG_VERBOSE, "\n");
+ }
+ DBG_DEBUG(DBG_VERBOSE, "%02x ", decode_value.value[j]);
+ }
+ DBG_DEBUG(DBG_VERBOSE, "\n\n");
+ }
+ return 0;
+}
+static int dfd_parse_tlv_eeprom(uint8_t *eeprom, uint32_t size, uint8_t main_type, tlv_decode_value_t *decode_value)
+{
+ bool ret;
+ tlvinfo_header_t *eeprom_hdr;
+ int j;
+
+ eeprom_hdr = (tlvinfo_header_t *) eeprom;
+ g_eeprom_size = size; /* eeprom real size */
+
+ if (!is_valid_tlvinfo_header(eeprom_hdr)) {
+ DBG_DEBUG(DBG_ERROR, "Failed to check tlv header.\n");
+ return -1;
+ }
+
+ if (!is_checksum_valid(eeprom)) {
+ DBG_DEBUG(DBG_ERROR, "Failed to check tlv crc.\n");
+ return -1;
+ }
+
+ ret = tlvinfo_decode_tlv(eeprom, main_type, decode_value);
+ if (!ret) {
+ DBG_DEBUG(DBG_ERROR, "No found type: %d\n", main_type);
+ return -1;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "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(DBG_VERBOSE, "\n");
+ }
+ DBG_DEBUG(DBG_VERBOSE, "%02x ", decode_value->value[j]);
+ }
+ DBG_DEBUG(DBG_VERBOSE, "\n\n");
+
+ return 0;
+}
+#if 0
+/* Parsing extends the custom TLV format */
+static int tlvinfo_find_wb_ext_tlv(tlv_decode_value_t *ext_tlv_value, uint8_t ext_type,
+ uint8_t *buf, uint32_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(DBG_VERBOSE, "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(DBG_VERBOSE, "\n");
+ }
+ DBG_DEBUG(DBG_VERBOSE, "%02x ", ext_tlv_value->value[eeprom_index]);
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "\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_DEBUG(DBG_ERROR, "tlv is not valid, eeprom_tlv->type 0x%x.\n", eeprom_tlv->type);
+ return -1;
+ }
+
+ DBG_DEBUG(DBG_VERBOSE, "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(DBG_VERBOSE, "eeprom_tlv->length %d.\n", eeprom_tlv->length);
+ *buf_len = eeprom_tlv->length;
+ return 0;
+ }
+ DBG_DEBUG(DBG_VERBOSE, "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_DEBUG(DBG_VERBOSE, "ext_type %d: tlv is not found.\n", ext_type);
+ return -1;
+}
+#endif
+/* Obtain EEPROM information */
+int dfd_tlvinfo_get_e2prom_info(uint8_t *eeprom, uint32_t size, dfd_tlv_type_t *tlv_type, uint8_t* buf, uint32_t *buf_len)
+{
+ tlv_decode_value_t decode_value;
+ int ret;
+
+ if (eeprom == NULL || tlv_type == NULL || buf == NULL) {
+ DBG_DEBUG(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_DEBUG(DBG_ERROR, "dfd_parse_tlv_eeprom failed ret %d.\n", ret);
+ return ret;
+ }
+
+ if (*buf_len >= decode_value.length) {
+ memcpy(buf, decode_value.value, decode_value.length);
+ *buf_len = decode_value.length;
+ return 0;
+ }
+ DBG_DEBUG(DBG_ERROR, "buf_len %d small than info_len %d.\n", *buf_len, decode_value.length);
+ return -1;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg.h
new file mode 100644
index 000000000000..1cc8143d1f30
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg.h
@@ -0,0 +1,247 @@
+/*
+ * A header definition for dfd_cfg driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __DFD_CFG_H__
+#define __DFD_CFG_H__
+
+#include
+
+#define DFD_KO_FILE_NAME_DIR "/etc/s3ip_sysfs_cfg/file_name/" /* Library configuration file name directory */
+#define DFD_KO_CFG_FILE_DIR "/etc/s3ip_sysfs_cfg/cfg_file/" /* Library configuration file directory */
+#define DFD_PUB_CARDTYPE_FILE "/sys/module/platform_common/parameters/dfd_my_type"
+
+#define DFD_CFG_CMDLINE_MAX_LEN (256) /* The maximum length of the command line is specified */
+#define DFD_CFG_NAME_MAX_LEN (256) /* The maximum length of a name is specified */
+#define DFD_CFG_VALUE_MAX_LEN (256) /* The maximum length of the configuration value */
+#define DFD_CFG_STR_MAX_LEN (64) /* The maximum length of a character string is specified */
+#define DFD_CFG_CPLD_NUM_MAX (16) /* Maximum number of cpld */
+#define DFD_PRODUCT_ID_LENGTH (8)
+#define DFD_PID_BUF_LEN (32)
+#define DFD_TEMP_NAME_BUF_LEN (32)
+
+#define DFD_CFG_EMPTY_VALUE (-1) /* Null configuration value */
+#define DFD_CFG_INVALID_VALUE (0) /* Configuring an illegal value */
+
+/* Set the key value of the binary tree */
+#define DFD_CFG_KEY(item, index1, index2) \
+ (((((uint64_t)item) & 0xffff) << 24) | (((index1) & 0xffff) << 8) | ((index2) & 0xff))
+#define DFD_CFG_ITEM_ID(key) (((key) >> 24) & 0xffff)
+#define DFD_CFG_INDEX1(key) (((key) >> 8) & 0xffff)
+#define DFD_CFG_INDEX2(key) ((key)& 0xff)
+
+/* Index range */
+#define INDEX_NOT_EXIST (-1)
+#define INDEX1_MAX (0xffff)
+#define INDEX2_MAX (0xff)
+
+#define DFD_CFG_ITEM_ALL \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_NONE, "none", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_DEV_NUM, "dev_num", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_BMC_SYSTEM_CMD_NUM, "bmc_system_cmd_num", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_THRESHOLD, "fan_threshold", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_LED_STATUS_DECODE, "led_status_decode", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_SYSTEM_STATUS_DECODE, "system_status_decode", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_LPC_DEV, "cpld_lpc_dev", INDEX1_MAX, DFD_CFG_CPLD_NUM_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_TYPE_NUM, "fan_type_num", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_EEPROM_SIZE, "eeprom_size", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_DECODE_POWER_FAN_DIR, "decode_power_fan_dir", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_WATCHDOG_ID, "watchdog_id", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_POWER_RSUPPLY, "power_rate_supply", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_DIRECTION, "fan_direction", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_TEMP_MONITOR_DC, "dc_monitor_flag_hwmon_temp", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_IN_MONITOR_FLAG_DC, "dc_monitor_flag_hwmon_in", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_CURR_MONITOR_FLAG_DC, "dc_monitor_flag_hwmon_curr", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_INT_END, "end_int", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_MODE, "mode_cpld", INDEX1_MAX, DFD_CFG_CPLD_NUM_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_NAME, "cpld_name", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_TYPE, "cpld_type", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FPGA_NAME, "fpga_name", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FPGA_TYPE, "fpga_type", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FPGA_MODEL_DECODE, "fpga_model_decode", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_E2_MODE, "fan_e2_mode", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_FRU_MODE, "psu_fru_mode", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_SYSFS_NAME, "fan_sysfs_name", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_POWER_NAME, "power_name", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_NAME, "fan_name", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_DECODE_POWER_NAME, "decode_power_name", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_SPEED_CAL, "fan_speed_cal", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_DECODE_FAN_NAME, "decode_fan_name", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_EEPROM_PATH, "eeprom_path", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_WATCHDOG_NAME, "watchdog_name", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_SYSFS_NAME, "psu_sysfs_name", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_SLOT_SYSFS_NAME, "slot_sysfs_name", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_EEPROM_ALIAS, "eeprom_alias", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_EEPROM_TAG, "eeprom_tag", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_EEPROM_TYPE, "eeprom_type", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_BLACKBOX_INFO, "psu_blackbox_info", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_PMBUS_INFO, "psu_pmbus_info", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_CLEAR_BLACKBOX, "psu_clear_blackbox", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_STRING_END, "end_string", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_I2C_DEV, "cpld_i2c_dev", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_OTHER_I2C_DEV, "other_i2c_dev", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_I2C_DEV_END, "end_i2c_dev", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+ \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_ROLL_STATUS, "fan_roll_status", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_SPEED, "fan_speed", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FAN_RATIO, "fan_ratio", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_LED_STATUS, "led_status", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_VERSION, "cpld_version", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_HW_VERSION, "cpld_hw_version", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CPLD_TEST_REG, "cpld_test_reg", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_DEV_PRESENT_STATUS, "dev_present_status", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_STATUS, "psu_status", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_TEMP, "hwmon_temp", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_TEMP_MONITOR_FLAG, "monitor_flag_hwmon_temp", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_IN, "hwmon_in", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_IN_MONITOR_FLAG, "monitor_flag_hwmon_in", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_CURR, "hwmon_curr", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_CURR_MONITOR_FLAG, "monitor_flag_hwmon_curr", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_PSU, "hwmon_psu", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_SFF_OPTOE_TYPE, "sff_optoe_type", INDEX1_MAX, INDEX_NOT_EXIST) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_HWMON_POWER, "hwmon_power", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_SFF_CPLD_REG, "sff_cpld_reg", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FPGA_VERSION, "fpga_version", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FPGA_TEST_REG, "fpga_test_reg", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_FPGA_MODEL_REG, "fpga_model_reg", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_PMBUS_REG, "psu_pmbus_reg", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_WATCHDOG_DEV, "watchdog_dev", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_BMC_SYSTEM, "bmc_system", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PRE_CHECK_BMC_SYSTEM, "pre_check_bmc_system", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM, "check_val_bmc_system", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_PSU_FRU_PMBUS, "psu_fru_pmbus", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_POWER_STATUS, "power_status", INDEX1_MAX, INDEX2_MAX) \
+ DFD_CFG_ITEM(DFD_CFG_ITEM_INFO_CTRL_END, "end_info_ctrl", INDEX_NOT_EXIST, INDEX_NOT_EXIST) \
+
+/* Configuration item id enumeration definition */
+#ifdef DFD_CFG_ITEM
+#undef DFD_CFG_ITEM
+#endif
+#define DFD_CFG_ITEM(_id, _name, _index_min, _index_max) _id,
+typedef enum dfd_cfg_item_id_s {
+ DFD_CFG_ITEM_ALL
+} dfd_cfg_item_id_t;
+
+#define DFD_CFG_ITEM_IS_INT(item_id) \
+ (((item_id) > DFD_CFG_ITEM_NONE) && ((item_id) < DFD_CFG_ITEM_INT_END))
+
+#define DFD_CFG_ITEM_IS_STRING(item_id) \
+ (((item_id) > DFD_CFG_ITEM_INT_END) && ((item_id) < DFD_CFG_ITEM_STRING_END))
+
+#define DFD_CFG_ITEM_IS_I2C_DEV(item_id) \
+ (((item_id) > DFD_CFG_ITEM_STRING_END) && ((item_id) < DFD_CFG_ITEM_I2C_DEV_END))
+
+#define DFD_CFG_ITEM_IS_INFO_CTRL(item_id) \
+ (((item_id) > DFD_CFG_ITEM_I2C_DEV_END) && ((item_id) < DFD_CFG_ITEM_INFO_CTRL_END))
+
+/* Index value range structure */
+typedef struct index_range_s {
+ int index1_max; /* The primary index indicates the maximum value */
+ int index2_max; /* Indicates the maximum value of the secondary index */
+} index_range_t;
+
+/* Register value conversion node */
+typedef struct val_convert_node_s {
+ struct list_head lst;
+ int int_val; /* Integer value */
+ char str_val[DFD_CFG_STR_MAX_LEN]; /* String value */
+ int index1; /* Index value 1 */
+ int index2; /* Index value 2 */
+} val_convert_node_t;
+
+/**
+ * dfd_ko_cfg_get_item - Get configuration item
+ * @key: Node key
+ *
+ * @returns: The NULL configuration item does not exist, and other configuration items are successful
+ */
+void *dfd_ko_cfg_get_item(uint64_t key);
+
+/**
+ * dfd_ko_cfg_show_item - Display configuration items
+ * @key: Node key
+ */
+void dfd_ko_cfg_show_item(uint64_t key);
+
+/**
+ * dfd_dev_cfg_init - Module initialization
+ *
+ * @returns: <0 Failed, otherwise succeeded
+ */
+int32_t dfd_dev_cfg_init(void);
+
+/**
+ * dfd_dev_cfg_exit - Module exit
+ *
+ * @returns: void
+ */
+void dfd_dev_cfg_exit(void);
+
+/* Strip out Spaces and carriage returns */
+void dfd_ko_cfg_del_space_lf_cr(char *str);
+
+void dfd_ko_cfg_del_lf_cr(char *str);
+
+/**
+ * dfd_ko_cfg_get_fan_direction_by_name - obtain the air duct type by fan name
+ * @fan_name: Fan name
+ * @fan_direction: Duct type
+ *
+ * @returns: 0 Succeeded, otherwise failed
+ */
+int dfd_ko_cfg_get_fan_direction_by_name(char *fan_name, int *fan_direction);
+
+/**
+ * dfd_ko_cfg_get_power_type_by_name - obtain the power supply type by power supply name
+ * @power_name: Power supply name
+ * @power_type: Power supply type
+ * @returns: 0 Succeeded, otherwise failed
+ */
+int dfd_ko_cfg_get_power_type_by_name(char *power_name, int *power_type);
+
+/**
+ * dfd_ko_cfg_get_led_status_decode2_by_regval - Reverse check the register value of the led status
+ * @regval: Defined led values
+ * @index1: led type
+ * @value: Gets the register value of the led status
+ * @returns: 0 Succeeded, otherwise failed
+ */
+int dfd_ko_cfg_get_led_status_decode2_by_regval(int regval, int index1, int *value);
+
+/**
+ * dfd_ko_cfg_get_fan_direction_by_name - obtain the fan type by fan name
+ * @fan_name: Fan name
+ * @fan_type: Fan type
+ * @sub_type: Fan sub-type
+ *
+ * @returns: 0 Succeeded, otherwise failed
+ */
+ int dfd_ko_cfg_get_fan_type_by_name(char *fan_name, int *fan_type, int *sub_type);
+
+ /**
+ * key_to_name - convert to name by key
+ * @key: Fan name
+ *
+ * @returns: name
+ */
+char *key_to_name(uint64_t key);
+
+#endif /* __DFD_CFG_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_adapter.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_adapter.h
new file mode 100644
index 000000000000..f70c46328e58
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_adapter.h
@@ -0,0 +1,136 @@
+/*
+ * A header definition for dfd_cfg_adapter driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __DFD_CFG_ADAPTER_H__
+#define __DFD_CFG_ADAPTER_H__
+
+#define DFD_KO_CPLD_I2C_RETRY_SLEEP (10) /* ms */
+#define DFD_KO_CPLD_I2C_RETRY_TIMES (50 / DFD_KO_CPLD_I2C_RETRY_SLEEP)
+
+#define DFD_KO_CPLD_GET_SLOT(addr) ((addr >> 24) & 0xff)
+#define DFD_KO_CPLD_GET_ID(addr) ((addr >> 16) & 0xff)
+#define DFD_KO_CPLD_GET_INDEX(addr) (addr & 0xffff)
+#define DFD_KO_CPLD_MODE_I2C_STRING "i2c"
+#define DFD_KO_CPLD_MODE_LPC_STRING "lpc"
+
+#define DFD_KO_OTHER_I2C_GET_MAIN_ID(addr) ((addr >> 24) & 0xff)
+#define DFD_KO_OTHER_I2C_GET_INDEX(addr) ((addr >> 16) & 0xff)
+#define DFD_KO_OTHER_I2C_GET_OFFSET(addr) (addr & 0xffff)
+#define DFD_SYSFS_PATH_MAX_LEN (64)
+
+typedef struct dfd_i2c_dev_s {
+ int bus; /* bus number */
+ int addr; /* Bus address */
+} dfd_i2c_dev_t;
+
+/* dfd_i2c_dev_t member macro */
+typedef enum dfd_i2c_dev_mem_s {
+ DFD_I2C_DEV_MEM_BUS,
+ DFD_I2C_DEV_MEM_ADDR,
+ DFD_I2C_DEV_MEM_END
+} dfd_i2c_dev_mem_t;
+
+typedef enum cpld_mode_e {
+ DFD_CPLD_MODE_I2C, /* I2C bus */
+ DFD_CPLD_MODE_LPC, /*LPC bus*/
+} cpld_mode_t;
+
+/* i2c access mode */
+typedef enum i2c_mode_e {
+ DFD_I2C_MODE_NORMAL_I2C, /* I2C bus */
+ DFD_I2C_MODE_SMBUS, /* SMBUS bus */
+} i2c_mode_t;
+
+/* Global variable */
+extern char *g_dfd_i2c_dev_mem_str[DFD_I2C_DEV_MEM_END]; /* dfd_i2c_dev_t member string */
+
+/**
+ * dfd_ko_cpld_read - cpld read operation
+ * @addr: Offset address
+ * @buf: data
+ *
+ * @returns: <0 Failed, others succeeded
+ */
+int32_t dfd_ko_cpld_read(int32_t addr, uint8_t *buf);
+
+/**
+ * dfd_ko_cpld_write - cpld write operation
+ * @addr: address
+ * @data: data
+ *
+ * @returns: <0 Failed, others succeeded
+ */
+int32_t dfd_ko_cpld_write(int32_t addr, uint8_t val);
+
+/**
+ * dfd_ko_i2c_read - I2C read operation
+ * @bus: I2C bus
+ * @addr: I2C device address
+ * @offset:register offset
+ * @buf:Read buffer
+ * @size:Read length
+ * @sysfs_name:sysfs attribute name
+ * @returns: <0 Failed, others succeeded
+ */
+int32_t dfd_ko_i2c_read(int bus, int addr, int offset, uint8_t *buf, uint32_t size, const char *sysfs_name);
+
+/**
+ * dfd_ko_i2c_write - I2C write operation
+ * @bus: I2C bus
+ * @addr: I2C device address
+ * @offset:register offset
+ * @buf:write buffer
+ * @size: write length
+ * @returns: <0 Failed, others succeeded
+ */
+int32_t dfd_ko_i2c_write(int bus, int addr, int offset, uint8_t *buf, uint32_t size);
+
+/**
+ * dfd_ko_read_file - File read operation
+ * @fpath: File path
+ * @addr: address
+ * @val: data
+ * @read_bytes: length
+ *
+ * @returns: <0 Failed, others succeeded
+ */
+int32_t dfd_ko_read_file(char *fpath, int32_t addr, uint8_t *val, int32_t read_bytes);
+
+/**
+ * dfd_ko_write_file - File write operation
+ * @fpath: File path
+ * @addr: address
+ * @val: data
+ * @write_bytes: length
+ *
+ * @returns: <0 Failed, others succeeded
+ */
+int32_t dfd_ko_write_file(char *fpath, int32_t addr, uint8_t *val, int32_t write_bytes);
+
+/**
+ * dfd_ko_other_i2c_dev_read - other_i2c read operation
+ * @addr: address
+ * @val: data
+ * @read_len: length
+ *
+ * @returns: <0 Failed, others succeeded
+ */
+int32_t dfd_ko_other_i2c_dev_read(int32_t addr, uint8_t *value, int32_t read_len);
+#endif /* __DFD_CFG_ADAPTER_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_file.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_file.h
new file mode 100644
index 000000000000..4eba8aabbd49
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_file.h
@@ -0,0 +1,101 @@
+/*
+ * A header definition for dfd_cfg_file driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __DFD_CFG_FILE_H__
+#define __DFD_CFG_FILE_H__
+
+#include
+
+/* Returned value */
+#define KFILE_RV_OK (0)
+#define KFILE_RV_INPUT_ERR (-1) /* Entry error */
+#define KFILE_RV_STAT_FAIL (-2) /* Failed to obtain file properties. Procedure */
+#define KFILE_RV_OPEN_FAIL (-3) /* Failed to open file */
+#define KFILE_RV_MALLOC_FAIL (-4) /* Failed to allocate memory */
+#define KFILE_RV_RD_FAIL (-5) /* Read failure */
+#define KFILE_RV_ADDR_ERR (-6) /* Address error */
+#define KFILE_RV_WR_FAIL (-7) /* Address error */
+
+/* Whether it is a newline character */
+#define IS_CR(c) ((c) == '\n')
+
+/* File operation control structure */
+typedef struct kfile_ctrl_s {
+ int32_t size; /* File size */
+ int32_t pos; /* Current position */
+ char *buf; /* File cache */
+} kfile_ctrl_t;
+
+/*
+ * Open file
+ * @fname: filename
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: 0 Succeeded, others failed
+ */
+int kfile_open(char *fname, kfile_ctrl_t *kfile_ctrl);
+
+/*
+ * Close file
+ * @kfile_ctrl: File control variable
+ */
+void kfile_close(kfile_ctrl_t *kfile_ctrl);
+
+/*
+ * Close file
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: >=0 Succeeded. Others failed
+ */
+int kfile_gets(char *buf, int buf_size, kfile_ctrl_t *kfile_ctrl);
+
+/*
+ * Read data
+ * @buf: buf Buffer area
+ * @buf_size: buf size
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: >=0 Succeeded. Others failed
+ */
+int kfile_read(int32_t addr, char *buf, int buf_size, kfile_ctrl_t *kfile_ctrl);
+
+/*
+ * Read data
+ * @buf: buf Buffer area
+ * @buf_size: buf size
+ * @kfile_ctrl: File control variable
+ *
+ * @returns: >=0 Succeeded. Others failed
+ */
+int kfile_iterate_dir(const char *dir_path, const char *obj_name, char *match_name, int len);
+
+#if 0
+/*
+ * Write data
+ * @fname: filename
+ * @addr: Offset address of the file written to
+ * @buf: Write data
+ * @buf_size: Data size
+ *
+ * @returns: >=0 Succeeded. Others failed
+ */
+int kfile_write(char *fpath, int32_t addr, char *buf, int buf_size);
+#endif
+#endif /* __DFD_CFG_FILE_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_info.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_info.h
new file mode 100644
index 000000000000..2e5dd2f3d645
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_info.h
@@ -0,0 +1,192 @@
+/*
+ * A header definition for dfd_cfg_info driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __DFD_CFG_INFO_H__
+#define __DFD_CFG_INFO_H__
+
+#include
+
+/* num buf format data to convert to a numeric function pointer */
+typedef int (*info_num_buf_to_value_f)(uint8_t *num_buf, int buf_len, int *num_val);
+
+/* num buf format data to convert to a numeric function pointer */
+typedef int (*info_buf_to_buf_f)(uint8_t *buf, int buf_len, uint8_t *buf_new, int *buf_len_new);
+
+/* Information format judgment macro */
+#define IS_INFO_FRMT_BIT(frmt) ((frmt) == INFO_FRMT_BIT)
+#define IS_INFO_FRMT_BYTE(frmt) (((frmt) == INFO_FRMT_BYTE) || ((frmt) == INFO_FRMT_NUM_BYTES))
+#define IS_INFO_FRMT_NUM_STR(frmt) ((frmt) == INFO_FRMT_NUM_STR)
+#define IS_INFO_FRMT_NUM_BUF(frmt) ((frmt) == INFO_FRMT_NUM_BUF)
+#define IS_INFO_FRMT_BUF(frmt) ((frmt) == INFO_FRMT_BUF)
+
+/* INT Validity judgment of information length */
+#define INFO_INT_MAX_LEN (32)
+#define INFO_INT_LEN_VALAID(len) (((len) > 0) && ((len) < INFO_INT_MAX_LEN))
+
+/* buf Validity judgment of information length */
+#define INFO_BUF_MAX_LEN (128)
+#define INFO_BUF_LEN_VALAID(len) (((len) > 0) && ((len) < INFO_BUF_MAX_LEN))
+
+/* Determine the validity of information bit offset */
+#define INFO_BIT_OFFSET_VALID(bit_offset) (((bit_offset) >= 0) && ((bit_offset) < 8))
+
+/* Information control mode */
+typedef enum info_ctrl_mode_e {
+ INFO_CTRL_MODE_NONE,
+ INFO_CTRL_MODE_CFG, /* Configuration mode */
+ INFO_CTRL_MODE_CONS, /* macromode */
+ INFO_CTRL_MODE_TLV, /* TLV mode */
+ INFO_CTRL_MODE_SRT_CONS, /* String constant*/
+ INFO_CTRL_MODE_END
+} info_ctrl_mode_t;
+
+/* Information format */
+typedef enum info_frmt_e {
+ INFO_FRMT_NONE,
+ INFO_FRMT_BIT, /* Single or multiple bits, not more than 8 bits */
+ INFO_FRMT_BYTE, /* Single byte */
+ INFO_FRMT_NUM_BYTES, /* Multiple byte values, up to sizeof(int) */
+ INFO_FRMT_NUM_STR, /* String value */
+ INFO_FRMT_NUM_BUF, /* String value */
+ INFO_FRMT_BUF, /* Multiple bytes */
+ INFO_FRMT_END
+} info_frmt_t;
+
+/* Information source */
+typedef enum info_src_e {
+ INFO_SRC_NONE,
+ INFO_SRC_CPLD, /* CPLD equipment */
+ INFO_SRC_FPGA, /* FPGA equipment */
+ INFO_SRC_OTHER_I2C, /* other i2c equipment */
+ INFO_SRC_FILE, /* file */
+ INFO_SRC_END
+} info_src_t;
+
+/* Polarity of information */
+typedef enum info_pola_e {
+ INFO_POLA_NONE,
+ INFO_POLA_POSI, /* Positive polarity bit value 1 Valid value high bytes saved in the source low address space */
+ INFO_POLA_NEGA, /* Negative polarity bit value 0 Effective value high bytes saved in the source high address space */
+ INFO_POLA_END
+} info_pola_t;
+
+/* Information control structure */
+#define INFO_FPATH_MAX_LEN (128) /* Maximum length of the file source path */
+#define INFO_STR_CONS_MAX_LEN (64) /* Maximum length of a string constant */
+typedef struct info_ctrl_s {
+ info_ctrl_mode_t mode; /* mode */
+ int32_t int_cons; /* Only the int type is supported */
+ info_src_t src; /* source */
+ info_frmt_t frmt; /* format */
+ info_pola_t pola; /* polarity */
+ char fpath[INFO_FPATH_MAX_LEN]; /* File path, only the file source information */
+ int32_t addr; /* address */
+ int32_t len; /* Length, bit length, or byte length */
+ int32_t bit_offset; /* Offset number of bits in the address */
+ char str_cons[INFO_STR_CONS_MAX_LEN]; /* String constant */
+ int32_t int_extra1; /* int type reserved */
+ int32_t int_extra2;
+ int32_t int_extra3; /* cpld voltage mode */
+} info_ctrl_t;
+
+/* info_ctrl_t member macro */
+typedef enum info_ctrl_mem_s {
+ INFO_CTRL_MEM_MODE,
+ INFO_CTRL_MEM_INT_CONS,
+ INFO_CTRL_MEM_SRC,
+ INFO_CTRL_MEM_FRMT,
+ INFO_CTRL_MEM_POLA,
+ INFO_CTRL_MEM_FPATH,
+ INFO_CTRL_MEM_ADDR,
+ INFO_CTRL_MEM_LEN,
+ INFO_CTRL_MEM_BIT_OFFSET,
+ INFO_CTRL_MEM_STR_CONS,
+ INFO_CTRL_MEM_INT_EXTRA1,
+ INFO_CTRL_MEM_INT_EXTRA2,
+ INFO_CTRL_MEM_INT_EXTRA3,
+ INFO_CTRL_MEM_END
+} info_ctrl_mem_t;
+
+/* sensor data format */
+typedef enum sensor_format_mem_s {
+ LINEAR11 = 1,
+ LINEAR16 = 2,
+ TMP464 = 3,
+ MAC_TH5 = 4,
+ MAC_TH4 = 5,
+} sensor_format_mem_t;
+
+/* hwmon data format conversion */
+typedef int (*info_hwmon_buf_f)(uint8_t *buf, int buf_len, uint8_t *buf_new, int *buf_len_new,
+ info_ctrl_t *info_ctrl, int coefficient, int addend);
+
+/* Global variable */
+extern char *g_info_ctrl_mem_str[INFO_CTRL_MEM_END]; /* info_ctrl_t member string */
+extern char *g_info_src_str[INFO_SRC_END]; /* info_src_t enumeration string */
+extern char *g_info_frmt_str[INFO_FRMT_END]; /* info_frmt_t enumeration string */
+extern char *g_info_pola_str[INFO_POLA_END]; /* info_pola_t enumeration string */
+extern char *g_info_ctrl_mode_str[INFO_CTRL_MODE_END];/* info_ctrl_mode_t enumeration string */
+
+/**
+ * dfd_info_get_int - Get int type information
+ * @key: Search keyword of the configuration item
+ * @ret: int type information
+ * @pfun: num Data conversion function of type buf
+ *
+ * @returns: 0 succeeds, <0 fails
+ */
+int dfd_info_get_int(uint64_t key, int *ret, info_num_buf_to_value_f pfun);
+
+/**
+ * dfd_info_get_buf - Get buf type information
+ * @key: Search keyword of the configuration item
+ * @buf: Information buf
+ * @buf_len: buf length, which must be no less than info_ctrl->len
+ * @pfun: Data conversion function pointer
+ *
+ * @returns: 0 succeeds, <0 fails
+ */
+int dfd_info_get_buf(uint64_t key, uint8_t *buf, int buf_len, info_buf_to_buf_f pfun);
+
+/**
+ * dfd_info_set_int - Set the int type information
+ * @key: Search keyword of the configuration item
+ * @val: int type information
+ *
+ * @returns: 0 succeeds, <0 fails
+ */
+int dfd_info_set_int(uint64_t key, int val);
+
+/**
+ * dfd_info_get_sensor - Get sensors
+ * @key: HWMON Configures the key
+ * @buf: Result storage
+ * @buf_len: buf length
+ *
+ * @returns: <0 Failed, others succeeded
+ */
+int dfd_info_get_sensor(uint64_t key, char *buf, int buf_len, info_hwmon_buf_f pfun);
+
+/**
+ * @buf:Input and result store
+ *
+ */
+void dfd_info_del_no_print_string(char *buf);
+#endif /* __DFD_CFG_INFO_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_listnode.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_listnode.h
new file mode 100644
index 000000000000..8b2b12ad512a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_cfg_listnode.h
@@ -0,0 +1,80 @@
+/*
+ * A header definition for dfd_cfg_listnode driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __DFD_CFG_LISTNODE_H__
+#define __DFD_CFG_LISTNODE_H__
+
+#include
+
+/* Returned value */
+#define LNODE_RV_OK (0)
+#define LNODE_RV_INPUT_ERR (-1) /* Entry error */
+#define LNODE_RV_NODE_EXIST (-2) /* Node already exists */
+#define LNODE_RV_NOMEM (-3) /* Node already exists */
+
+/* Root node public structure */
+typedef struct lnode_root_s {
+ struct list_head root;
+} lnode_root_t;
+
+/* Node structure */
+typedef struct lnode_node_s {
+ struct list_head lst;
+
+ uint64_t key; /* Node search index value */
+ void *data; /* The actual data pointer */
+} lnode_node_t;
+
+/**
+ * Find node
+ * @root: Root node pointer
+ * @key: Node index value
+ *
+ * @return : Node data pointer,NULL failed
+ */
+void *lnode_find_node(lnode_root_t *root, uint64_t key);
+
+/**
+ * Insert node
+ * @root: Root node pointer
+ * @key: Node index value
+ * @data: data
+ *
+ * @return : 0-- success, other failures
+ */
+int lnode_insert_node(lnode_root_t *root, uint64_t key, void *data);
+
+/**
+ * Example Initialize the root node
+ * @root: Root node pointer
+ *
+ * @return : 0-- success, other failures
+ */
+int lnode_init_root(lnode_root_t *root);
+
+/**
+ * Free linked list
+ * @root: Root node pointer
+ *
+ * @return : void
+ */
+void lnode_free_list(lnode_root_t *root);
+
+#endif /* __DFD_CFG_LISTNODE_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_frueeprom.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_frueeprom.h
new file mode 100644
index 000000000000..a95943c5a90d
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_frueeprom.h
@@ -0,0 +1,107 @@
+/*
+ * A header definition for dfd_cfg_frueeprom driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DFD_FRUEEPROM_H_
+#define _DFD_FRUEEPROM_H_
+
+/* Per IPMI v2.0 FRU specification */
+typedef struct fru_common_header_s {
+ uint8_t fixed;
+ uint8_t internal_offset;
+ uint8_t chassis_offset;
+ uint8_t board_offset;
+ uint8_t product_offset;
+ uint8_t multi_offset;
+ uint8_t pad;
+ uint8_t crc;
+} __attribute__((packed)) fru_common_header_t;
+
+/* first byte in header is 1h per IPMI V2 spec. */
+
+#define IPMI_FRU_HDR_BYTE_ZERO 1
+#define IPMI_EIGHT_BYTES 8
+#define IPMI_FRU_PRODUCT_AREA_MIN_LEN (7)
+#define IPMI_FRU_BOARD_AREA_MIN_LEN (5)
+
+#define IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX 512
+#define IPMI_FRU_BOARD_INFO_MFG_TIME_LENGTH 3
+#define IPMI_FRU_SENTINEL_VALUE 0xC1
+#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_MASK 0xC0
+#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_SHIFT 0x06
+#define IPMI_FRU_TYPE_LENGTH_NUMBER_OF_DATA_BYTES_MASK 0x3F
+#define IPMI_FRU_TYPE_LENGTH_TYPE_CODE_LANGUAGE_CODE 0x03
+
+struct ipmi_fru_field {
+ uint8_t type_length_field[IPMI_FRU_AREA_TYPE_LENGTH_FIELD_MAX];
+ /* store length of data stored in buffer */
+ unsigned int type_length_field_length;
+};
+
+typedef struct ipmi_fru_field ipmi_fru_field_t;
+
+typedef struct ipmi_product_info_s {
+ uint8_t *language_code;
+ ipmi_fru_field_t *product_manufacturer_name;
+ ipmi_fru_field_t *product_name;
+ ipmi_fru_field_t *product_part_model_number;
+ ipmi_fru_field_t *product_version;
+ ipmi_fru_field_t *product_serial_number;
+ ipmi_fru_field_t *product_asset_tag;
+ ipmi_fru_field_t *product_fru_file_id;
+ ipmi_fru_field_t *product_custom_fields;
+ ipmi_fru_field_t *product_type_fields;
+} ipmi_product_info_t;
+
+typedef struct ipmi_board_info_s {
+ uint8_t *language_code;
+ uint8_t *mfg_time;
+ ipmi_fru_field_t *board_manufacturer;
+ ipmi_fru_field_t *board_product_name;
+ ipmi_fru_field_t *board_serial_number;
+ ipmi_fru_field_t *board_part_number;
+ ipmi_fru_field_t *board_fru_file_id;
+ ipmi_fru_field_t *board_custom_fields; /*hw version */
+} ipmi_board_info_t;
+
+/**
+ * dfd_get_fru_data - Obtain product area FRU information
+ * @bus:FRU E2 bus number
+ * @dev_addr:FRU E2 Device address
+ * @type: 2: Product name, 3: product serial number 5: hardware version number 6: product ID
+ * @buf:Data is stored in buf
+ * @buf_len:buf length
+ * @sysfs_name:sysfs attribute name
+ * @returns: 0 success, negative value: failed
+ */
+int dfd_get_fru_data(int bus, int dev_addr, int type, uint8_t *buf, uint32_t buf_len, const char *sysfs_name);
+
+/**
+ * dfd_get_fru_board_data - Obtain the FRU information of the board area
+ * @bus:FRU E2 bus number
+ * @dev_addr:FRU E2 Device address
+ * @type: 2: Product name, 3: product serial number 5: hardware version number
+ * @buf:Data is stored in buf
+ * @buf_len:buf length
+ * @sysfs_name:sysfs attribute name
+ * @returns: 0 success, negative value: failed
+ */
+int dfd_get_fru_board_data(int bus, int dev_addr, int type, uint8_t *buf, uint32_t buf_len, const char *sysfs_name);
+
+#endif /* endif _DFD_FRUEEPROM_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_sysfs_common.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_sysfs_common.h
new file mode 100644
index 000000000000..994bb2387ddb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_sysfs_common.h
@@ -0,0 +1,251 @@
+/*
+ * A header definition for dfd_sysfs_common driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DFD_SYSFS_COMMON_H_
+#define _DFD_SYSFS_COMMON_H_
+
+struct switch_drivers_s {
+ /* temperature sensors */
+ int (*get_main_board_temp_number)(void);
+ ssize_t (*get_main_board_temp_alias)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_type)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_max)(unsigned int temp_index, char *buf, size_t count);
+ int (*set_main_board_temp_max)(unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_temp_min)(unsigned int temp_index, char *buf, size_t count);
+ int (*set_main_board_temp_min)(unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_temp_value)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_high)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_low)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_monitor_flag)(unsigned int temp_index, char *buf, size_t count);
+ /* voltage sensors */
+ int (*get_main_board_vol_number)(void);
+ ssize_t (*get_main_board_vol_alias)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_type)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_max)(unsigned int vol_index, char *buf, size_t count);
+ int (*set_main_board_vol_max)(unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_vol_min)(unsigned int vol_index, char *buf, size_t count);
+ int (*set_main_board_vol_min)(unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_vol_range)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_nominal_value)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_value)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_monitor_flag)(unsigned int vol_index, char *buf, size_t count);
+ /* current sensors */
+ int (*get_main_board_curr_number)(void);
+ ssize_t (*get_main_board_curr_alias)(unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_main_board_curr_type)(unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_main_board_curr_max)(unsigned int curr_index, char *buf, size_t count);
+ int (*set_main_board_curr_max)(unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_curr_min)(unsigned int curr_index, char *buf, size_t count);
+ int (*set_main_board_curr_min)(unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_curr_value)(unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_main_board_curr_monitor_flag)(unsigned int curr_index, char *buf, size_t count);
+ /* syseeprom */
+ int (*get_syseeprom_size)(void);
+ ssize_t (*read_syseeprom_data)(char *buf, loff_t offset, size_t count);
+ ssize_t (*write_syseeprom_data)(char *buf, loff_t offset, size_t count);
+ /* fan */
+ int (*get_fan_number)(void);
+ int (*get_fan_motor_number)(unsigned int fan_index);
+ ssize_t (*get_fan_model_name)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_vendor)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_serial_number)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_part_number)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_hardware_version)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_status)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_present)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_led_status)(unsigned int fan_index, char *buf, size_t count);
+ int (*set_fan_led_status)(unsigned int fan_index, int status);
+ ssize_t (*get_fan_direction)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_status)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_tolerance)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_target)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_max)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_min)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_ratio)(unsigned int fan_index, char *buf, size_t count);
+ int (*set_fan_ratio)(unsigned int fan_index, int ratio);
+ /* PSU */
+ int (*get_psu_number)(void);
+ int (*get_psu_temp_number)(unsigned int psu_index);
+ ssize_t (*get_psu_model_name)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_vendor)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_date)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_hw_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_alarm)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_serial_number)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_part_number)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_hardware_version)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_type)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_curr)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_vol)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_power)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_curr)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_vol)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_power)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_max_power)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_present_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_status_pmbus)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_fan_speed)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_fan_ratio)(unsigned int psu_index, char *buf, size_t count);
+ int (*set_psu_fan_ratio)(unsigned int psu_index, int ratio);
+ ssize_t (*get_psu_fan_direction)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_led_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_fan_speed_cal)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_temp_alias)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_psu_temp_type)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_psu_temp_max)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_psu_temp_max)(unsigned int psu_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_psu_temp_min)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_psu_temp_min)(unsigned int psu_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_psu_temp_value)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_psu_attr_threshold)(unsigned int psu_index, unsigned int type, char *buf, size_t count);
+ int (*get_psu_eeprom_size)(unsigned int psu_index);
+ ssize_t (*read_psu_eeprom_data)(unsigned int psu_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*get_psu_blackbox_info)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_pmbus_info)(unsigned int psu_index, char *buf, size_t count);
+ int (*clear_psu_blackbox)(unsigned int psu_index, uint8_t value);
+ /* transceiver */
+ int (*get_eth_number)(void);
+ ssize_t (*get_transceiver_power_on_status)(char *buf, size_t count);
+ int (*set_transceiver_power_on_status)(int status);
+ ssize_t (*get_transceiver_present_status)(char *buf, size_t count);
+ ssize_t (*get_eth_power_on_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*set_eth_power_on_status)(unsigned int eth_index, int status);
+ ssize_t (*get_eth_tx_fault_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_tx_disable_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*set_eth_tx_disable_status)(unsigned int eth_index, int status);
+ ssize_t (*get_eth_present_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_rx_los_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_reset_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*set_eth_reset_status)(unsigned int eth_index, int status);
+ ssize_t (*get_eth_low_power_mode_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_interrupt_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*get_eth_eeprom_size)(unsigned int eth_index);
+ ssize_t (*read_eth_eeprom_data)(unsigned int eth_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*write_eth_eeprom_data)(unsigned int eth_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*get_eth_optoe_type)(unsigned int sff_index, int *optoe_type, char *buf, size_t count);
+ int (*set_eth_optoe_type)(unsigned int sff_index, int optoe_type);
+ /* sysled */
+ ssize_t (*get_sys_led_status)(char *buf, size_t count);
+ int (*set_sys_led_status)(int status);
+ ssize_t (*get_bmc_led_status)(char *buf, size_t count);
+ int (*set_bmc_led_status)(int status);
+ ssize_t (*get_sys_fan_led_status)(char *buf, size_t count);
+ int (*set_sys_fan_led_status)(int status);
+ ssize_t (*get_sys_psu_led_status)(char *buf, size_t count);
+ int (*set_sys_psu_led_status)(int status);
+ ssize_t (*get_id_led_status)(char *buf, size_t count);
+ int (*set_id_led_status)(int status);
+ /* FPGA */
+ int (*get_main_board_fpga_number)(void);
+ ssize_t (*get_main_board_fpga_alias)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_type)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_firmware_version)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_board_version)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_test_reg)(unsigned int fpga_index, char *buf, size_t count);
+ int (*set_main_board_fpga_test_reg)(unsigned int fpga_index, unsigned int value);
+ /* CPLD */
+ int (*get_main_board_cpld_number)(void);
+ ssize_t (*get_main_board_cpld_alias)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_type)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_firmware_version)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_board_version)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_test_reg)(unsigned int cpld_index, char *buf, size_t count);
+ int (*set_main_board_cpld_test_reg)(unsigned int cpld_index, unsigned int value);
+ /* watchdog */
+ ssize_t (*get_watchdog_identify)(char *buf, size_t count);
+ ssize_t (*get_watchdog_timeleft)(char *buf, size_t count);
+ ssize_t (*get_watchdog_timeout)(char *buf, size_t count);
+ int (*set_watchdog_timeout)(int value);
+ ssize_t (*get_watchdog_enable_status)(char *buf, size_t count);
+ int (*set_watchdog_enable_status)(int value);
+ int (*set_watchdog_reset)(int value);
+ /* slot */
+ int (*get_slot_number)(void);
+ int (*get_slot_temp_number)(unsigned int slot_index);
+ int (*get_slot_vol_number)(unsigned int slot_index);
+ int (*get_slot_curr_number)(unsigned int slot_index);
+ int (*get_slot_cpld_number)(unsigned int slot_index);
+ int (*get_slot_fpga_number)(unsigned int slot_index);
+ ssize_t (*get_slot_model_name)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_vendor)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_serial_number)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_part_number)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_hardware_version)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_status)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_led_status)(unsigned int slot_index, char *buf, size_t count);
+ int (*set_slot_led_status)(unsigned int slot_index, int status);
+ ssize_t (*get_slot_power_status)(unsigned int slot_index, char *buf, size_t count);
+ int (*set_slot_power_status)(unsigned int slot_index, int status);
+ ssize_t (*get_slot_temp_alias)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_slot_temp_type)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_slot_temp_max)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_slot_temp_max)(unsigned int slot_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_slot_temp_min)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_slot_temp_min)(unsigned int slot_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_slot_temp_value)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_alias)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_type)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_max)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ int (*set_slot_vol_max)(unsigned int slot_index, unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_slot_vol_min)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ int (*set_slot_vol_min)(unsigned int slot_index, unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_slot_vol_range)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_nominal_value)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_value)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_curr_alias)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_slot_curr_type)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_slot_curr_max)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ int (*set_slot_curr_max)(unsigned int slot_index, unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_slot_curr_min)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ int (*set_slot_curr_min)(unsigned int slot_index, unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_slot_curr_value)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_alias)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_type)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_firmware_version)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_board_version)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_test_reg)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ int (*set_slot_fpga_test_reg)(unsigned int slot_index, unsigned int fpga_index, unsigned int value);
+ ssize_t (*get_slot_cpld_alias)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_type)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_firmware_version)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_board_version)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_test_reg)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ int (*set_slot_cpld_test_reg)(unsigned int slot_index, unsigned int cpld_index, unsigned int value);
+ /* system */
+ ssize_t (*get_system_value)(unsigned int type, int *value, char *buf, size_t count);
+ ssize_t (*set_system_value)(unsigned int type, int value);
+ ssize_t (*get_system_port_power_status)(unsigned int type, char *buf, size_t count);
+ /* eeprom */
+ int (*get_eeprom_number)(void);
+ int (*get_eeprom_size)(unsigned int e2_index);
+ ssize_t (*get_eeprom_alias)(unsigned int e2_index, char *buf, size_t count);
+ ssize_t (*get_eeprom_tag)(unsigned int e2_index, char *buf, size_t count);
+ ssize_t (*get_eeprom_type)(unsigned int e2_index, char *buf, size_t count);
+ ssize_t (*read_eeprom_data)(unsigned int e2_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*write_eeprom_data)(unsigned int e2_index, char *buf, loff_t offset, size_t count);
+};
+
+extern struct switch_drivers_s * s3ip_switch_driver_get(void);
+
+#endif /*_DFD_SYSFS_COMMON_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_tlveeprom.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_tlveeprom.h
new file mode 100644
index 000000000000..75e0f06bd305
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/dfd_tlveeprom.h
@@ -0,0 +1,91 @@
+/*
+ * A header definition for dfd_tlveeprom driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _DFD_TLVEEPROM_H_
+#define _DFD_TLVEEPROM_H_
+
+#ifndef be16_to_cpu
+#define be16_to_cpu(x) ntohs(x)
+#endif
+
+#ifndef cpu_to_be16
+#define cpu_to_be16(x) htons(x)
+#endif
+
+#define TLV_CODE_NAME_LEN 64
+
+/*
+ * Struct for displaying the TLV codes and names.
+ */
+struct tlv_code_desc {
+ uint8_t m_code;
+ char m_name[TLV_CODE_NAME_LEN];
+};
+
+/* ONIE TLV Type Type and extended TLV type definition */
+typedef struct dfd_tlv_type_s {
+ uint8_t main_type; /* ONIE standard TLV TYPE */
+ uint8_t ext_type; /* Extended TLV TYPE type */
+} dfd_tlv_type_t;
+
+/* Header Field Constants */
+#define TLV_INFO_ID_STRING "TlvInfo"
+#define TLV_INFO_VERSION 0x01
+
+struct __attribute__ ((__packed__)) tlvinfo_header_s {
+ char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */
+ uint8_t version; /* 0x08 Structure version */
+ uint16_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 {
+ uint8_t type;
+ uint8_t length;
+ uint8_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 {
+ uint8_t value[TLV_DECODE_VALUE_MAX_LEN];
+ uint32_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;
+
+int dfd_tlvinfo_get_e2prom_info(uint8_t *eeprom, uint32_t size, dfd_tlv_type_t *tlv_type, uint8_t* buf, uint32_t *buf_len);
+
+#endif /* endif _DFD_TLVEEPROM_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/switch_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/switch_driver.h
new file mode 100644
index 000000000000..7ab38f42d367
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/switch_driver.h
@@ -0,0 +1,101 @@
+/*
+ * A header definition for switch_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SWITCH_DRIVER_H_
+#define _SWITCH_DRIVER_H_
+
+#define SWITCH_DEV_NO_SUPPORT "NA"
+#define SWITCH_DEV_ERROR "ACCESS FAILED"
+#define WB_SYSFS_RV_UNSUPPORT (999)
+
+typedef enum dbg_level_e {
+ DBG_VERBOSE = 0x01,
+ DBG_WARN = 0x02,
+ DBG_ERROR = 0x04,
+} dbg_level_t;
+
+typedef enum fan_status_e {
+ FAN_STATUS_ABSENT = 0,
+ FAN_STATUS_OK = 1,
+ FAN_STATUS_NOT_OK = 2,
+} fan_status_t;
+
+typedef enum led_status_e {
+ LED_STATUS_DARK = 0,
+ LED_STATUS_GREEN = 1,
+ LED_STATUS_YELLOW = 2,
+ LED_STATUS_RED = 3,
+ LED_STATUS_BLUE = 4,
+ LED_STATUS_GREEN_FLASH = 5,
+ LED_STATUS_YELLOW_FLASH = 6,
+ LED_STATUS_RED_FLASH = 7,
+} led_status_t;
+
+typedef enum air_flow_direction_e {
+ F2B = 0, /* air enters from the front of the cabinet, and exhausts from the back */
+ B2F = 1, /* air enters from the back of the cabinet, and exhausts from the front */
+} air_flow_direction_t;
+
+typedef enum psu_input_type_e {
+ POWER_DC = 0,
+ POWER_AC = 1,
+} psu_input_type_t;
+
+typedef enum psu_status_e {
+ PSU_STATUS_ABSENT = 0, /* psu absent */
+ PSU_STATUS_PRESENT = 1, /* psu present and status ok */
+ PSU_STATUS_WARN = 2, /* psu present and status warn (pmbus 0x79 bit11 value 0)*/
+ PSU_STATUS_FAIL = 3, /* psu present and status fail (pmbus 0x79 bit11 value 1)*/
+} psu_status_t;
+
+typedef enum psu_status_word_e {
+ PSU_VOUT_FAULT = 0x8000,
+ PSU_IOUT_FAULT = 0x4000,
+ PSU_INPUT_FAULT = 0x2000,
+ PSU_MFR_FAULT = 0x1000,
+ PSU_PG_FAULT = 0x0800,
+ PSU_FAN_FAULT = 0x0400,
+ PSU_OFF_FAULT = 0x0040,
+ PSU_TEMP_FAULT = 0x0004,
+} psu_status_word_t;
+
+typedef enum psu_io_status_e {
+ PSU_IO_STATUS_ABNORMAL = 0,
+ PSU_IO_STATUS_NORMAL = 1,
+} psu_io_status_t;
+
+typedef enum dev_status_e {
+ DEV_ABSENT = 0, /* dev absent */
+ DEV_PRESENT = 1, /* dev present */
+} dev_status_t;
+
+extern int g_switch_dbg_level;
+
+#define SWITCH_DEBUG(level, fmt, arg...) do { \
+ if (g_switch_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#endif /* _SWITCH_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_cpld_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_cpld_driver.h
new file mode 100644
index 000000000000..7698a3f0ef60
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_cpld_driver.h
@@ -0,0 +1,100 @@
+/*
+ * A header definition for wb_cpld_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_CPLD_DRIVER_H_
+#define _WB_CPLD_DRIVER_H_
+
+/**
+ * dfd_get_cpld_name - Obtain the CPLD name
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * :Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_name(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count);
+
+/**
+ * dfd_get_cpld_type - Obtain the CPLD model
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * :Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_type(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count);
+
+/**
+ * dfd_get_cpld_fw_version - Obtain the CPLD firmware version
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * :Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_fw_version(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count);
+
+/**
+ * dfd_get_cpld_hw_version - Obtain the hardware version of the CPLD
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * :Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_hw_version(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count);
+
+/**
+ * dfd_set_cpld_testreg - Set the CPLD test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @cpld_index:The number of the CPLD starts from 0
+ * @value: Writes the value of the test register
+ * return: Success:0
+ * :Failed: A negative value is returned
+ */
+int dfd_set_cpld_testreg(uint8_t main_dev_id, unsigned int cpld_index, int value);
+
+/**
+ * dfd_get_cpld_testreg - Read the CPLD test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @cpld_index:The number of the CPLD starts from 0
+ * @value: Read the test register value
+ * return: Success:0
+ * :Failed: A negative value is returned
+ */
+int dfd_get_cpld_testreg(uint8_t main_dev_id, unsigned int cpld_index, int *value);
+
+/**
+ * dfd_get_cpld_testreg_str - Read the CPLD test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @cpld_index: The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * :Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_testreg_str(uint8_t main_dev_id, unsigned int cpld_index,
+ char *buf, size_t count);
+
+#endif /* _WB_CPLD_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_eeprom_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_eeprom_driver.h
new file mode 100644
index 000000000000..e86ee210be78
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_eeprom_driver.h
@@ -0,0 +1,59 @@
+/*
+ * A header definition for wb_eeprom_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_EEPROM_DRIVER_H_
+#define _WB_EEPROM_DRIVER_H_
+
+/**
+ * dfd_get_eeprom_size - Gets the data size of the eeprom
+ * @e2_type: This section describes the E2 type, including system, PSU, fan, and module E2
+ * @index: E2 number
+ * return: Succeeded: The data size of the eeprom is returned
+ * : Failed: A negative value is returned
+ */
+int dfd_get_eeprom_size(int e2_type, int index);
+
+/**
+ * dfd_read_eeprom_data - Read eeprom data
+ * @e2_type: This section describes the E2 type, including system, PSU, fan, and module E2
+ * @index: E2 number
+ * @buf: eeprom data received buf
+ * @offset: The offset address of the read
+ * @count: Read length
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_read_eeprom_data(int e2_type, int index, char *buf, loff_t offset, size_t count);
+
+/**
+ * dfd_write_eeprom_data - Write eeprom data
+ * @e2_type: This section describes the E2 type, including system, PSU, fan, and module E2
+ * @index: E2 number
+ * @buf: eeprom data buf
+ * @offset: The offset address of the write
+ * @count: Write length
+ * return: Success: The length of the written data is returned
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_write_eeprom_data(int e2_type, int index, char *buf, loff_t offset, size_t count);
+ssize_t dfd_get_eeprom_alias(int e2_type, unsigned int e2_index, char *buf, size_t count);
+ssize_t dfd_get_eeprom_tag(int e2_type, unsigned int e2_index, char *buf, size_t count);
+ssize_t dfd_get_eeprom_type(int e2_type, unsigned int e2_index, char *buf, size_t count);
+#endif /* _WB_EEPROM_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_fan_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_fan_driver.h
new file mode 100644
index 000000000000..b1e66cb0530c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_fan_driver.h
@@ -0,0 +1,191 @@
+/*
+ * A header definition for wb_fan_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_FAN_DRIVER_H_
+#define _WB_FAN_DRIVER_H_
+
+/**
+ * dfd_get_fan_status_str - Obtaining fan status
+ * @index: Number of the fan, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_fan_status_str(unsigned int fan_index, char *buf, size_t count);
+
+/**
+ * dfd_get_fan_present_str - Obtaining fan present status
+ * @index: Number of the fan, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_fan_present_str(unsigned int fan_index, char *buf, size_t count);
+
+/**
+ * dfd_get_fan_info - Obtaining Fan Information
+ * @index: Number of the fan, starting from 1
+ * @cmd: Fan information type, fan name :2, fan serial number :3, fan hardware version :5
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+
+/**
+ * dfd_get_fan_motor_status_str - Obtain the fan motor status
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_status_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count);
+
+ssize_t dfd_get_fan_info(unsigned int fan_index, uint8_t cmd, char *buf, size_t count);
+
+/**
+ * dfd_get_fan_speed - Obtain the fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @speed: Speed value
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_fan_speed(unsigned int fan_index, unsigned int motor_index,unsigned int *speed);
+
+/**
+ * dfd_get_fan_speed_str - Obtain the fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_speed_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count);
+
+/**
+ * dfd_set_fan_pwm - Set the fan speed duty cycle
+ * @fan_index: Number of the fan, starting from 1
+ * @pwm: Duty cycle
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_set_fan_pwm(unsigned int fan_index, int pwm);
+
+/**
+ * dfd_get_fan_pwm - Obtain the fan speed duty cycle
+ * @fan_index: Number of the fan, starting from 1
+ * @pwm: Duty cycle
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_fan_pwm(unsigned int fan_index, int *pwm);
+
+/**
+ * dfd_get_fan_pwm_str - Obtain the fan speed duty cycle
+ * @fan_index: Number of the fan, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_pwm_str(unsigned int fan_index, char *buf, size_t count);
+
+/**
+ * dfd_get_fan_motor_speed_tolerance_str - Obtain the fan speed tolerance
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_tolerance_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count);
+
+/**
+ * dfd_get_fan_speed_target - Obtain the standard fan speed
+ * @fan_index
+ * @motor_index
+ * @value Standard speed value
+ * @returns: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_fan_speed_target(unsigned int fan_index, unsigned int motor_index, int *value);
+
+/**
+ * dfd_get_fan_motor_speed_target_str - Obtain the standard fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_target_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count);
+
+/**
+ * dfd_get_fan_direction_str - Obtain the fan air duct type
+ * @fan_index: Number of the fan, starting from 1
+ * @buf :Duct type receives buf
+ * @count :Duct type receives buf length
+ * @returns: Succeeded: Air duct type String length
+ * Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_direction_str(unsigned int fan_index, char *buf, size_t count);
+
+/**
+ * dfd_get_fan_motor_speed_max_str - Obtain the standard fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buff
+ * @count: Receive buf length
+ * return: Success :0
+ * :Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_max_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count);
+
+/**
+ * dfd_get_fan_motor_speed_min_str - Obtain the standard fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_min_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count);
+
+/**
+ * dfd_get_fan_present_status - Obtain the fan status
+ * @index: Number of the fan, starting from 1
+ * return: 0:ABSENT
+ * 1:PRESENT
+ * : Negative value - Read failed
+ */
+int dfd_get_fan_present_status(unsigned int fan_index);
+
+#endif /* _WB_FAN_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_fpga_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_fpga_driver.h
new file mode 100644
index 000000000000..05863c4737af
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_fpga_driver.h
@@ -0,0 +1,100 @@
+/*
+ * A header definition for wb_fpga_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_FPGA_DRIVER_H_
+#define _WB_FPGA_DRIVER_H_
+
+/**
+ * dfd_get_fpga_name -Get the FPGA name
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:Number of the FPGA, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_name(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count);
+
+/**
+ * dfd_get_fpga_type - Get FPGA model
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:Number of the FPGA, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_type(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count);
+
+/**
+ * dfd_get_fpga_fw_version - Obtain the FPGA firmware version
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:Number of the FPGA, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_fw_version(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count);
+
+/**
+ * dfd_get_fpga_hw_version - Obtain the hardware version of the FPGA
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:Number of the FPGA, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_hw_version(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count);
+
+/**
+ * dfd_set_fpga_testreg - Sets the value of the FPGA test register
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @fpga_index:Number of the FPGA, starting from 1
+ * @value: Writes the value of the test register
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_set_fpga_testreg(uint8_t main_dev_id, unsigned int fpga_index, int value);
+
+/**
+ * dfd_get_fpga_testreg - Read the FPGA test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @fpga_index: Number of the FPGA, starting from 1
+ * @value: Read the test register value
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_fpga_testreg(uint8_t main_dev_id, unsigned int fpga_index, int *value);
+
+/**
+ * dfd_get_fpga_testreg_str - Read the FPGA test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @fpga_index:Number of the FPGA, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_testreg_str(uint8_t main_dev_id, unsigned int fpga_index,
+ char *buf, size_t count);
+
+#endif /* _WB_FPGA_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_led_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_led_driver.h
new file mode 100644
index 000000000000..bac7b23d9836
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_led_driver.h
@@ -0,0 +1,45 @@
+/*
+ * A header definition for wb_led_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_LED_DRIVER_H_
+#define _WB_LED_DRIVER_H_
+
+/**
+ * dfd_get_led_status - Get LED and other status
+ * @led_id: led lamp type
+ * @led_index: led light offset
+ * @buf: LED light status receives buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_led_status(uint16_t led_id, uint8_t led_index, char *buf, size_t count);
+
+/**
+ * dfd_set_led_status - Set LED light status
+ * @led_id: led lamp type
+ * @led_index: led light offset
+ * @value: LED light status value
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_set_led_status(uint16_t led_id, uint8_t led_index, int value);
+
+#endif /* _WB_LED_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_module.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_module.h
new file mode 100644
index 000000000000..6bce2817cb13
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_module.h
@@ -0,0 +1,360 @@
+/*
+ * A header definition for wb_module driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_MODULE_H_
+#define _WB_MODULE_H_
+
+#include "switch_driver.h"
+
+#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_INVALID_VALUE = 12,
+ DFD_RV_NO_MEMORY = 13,
+ DFD_RV_CHECK_FAIL = 14,
+} dfd_rv_t;
+
+typedef enum status_mem_e {
+ STATUS_ABSENT = 0,
+ STATUS_OK = 1,
+ STATUS_NOT_OK = 2,
+ STATUS_MEM_END = 3,
+} status_mem_t;
+
+/* psu PMBUS */
+typedef enum psu_sensors_type_e {
+ PSU_SENSOR_NONE = 0,
+ PSU_IN_VOL = 1,
+ PSU_IN_CURR = 2,
+ PSU_IN_POWER = 3,
+ PSU_OUT_VOL = 4,
+ PSU_OUT_CURR = 5,
+ PSU_OUT_POWER = 6,
+ PSU_FAN_SPEED = 7,
+ PSU_OUT_MAX_POWERE = 8,
+ PSU_OUT_STATUS = 9,
+ PSU_IN_STATUS = 10,
+ PSU_IN_TYPE = 11,
+ PSU_FAN_RATIO = 12,
+ PSU_IN_VOL_MAX = 13,
+ PSU_IN_CURR_MAX = 14,
+ PSU_IN_VOL_MIN = 15,
+ PSU_IN_CURR_MIN = 16,
+ PSU_OUT_VOL_MAX = 17,
+ PSU_OUT_CURR_MAX = 18,
+ PSU_OUT_VOL_MIN = 19,
+ PSU_OUT_CURR_MIN = 20,
+ PSU_FAN_SPEED_MAX = 21,
+ PSU_FAN_SPEED_MIN = 22,
+ PSU_IN_POWER_MAX = 23,
+ PSU_IN_POWER_MIN = 24,
+ PSU_OUT_POWER_MAX = 25,
+ PSU_OUT_POWER_MIN = 26,
+ PSU_HW_STATUS = 27,
+} psu_sensors_type_t;
+
+/* Watchdog type */
+typedef enum wb_wdt_type_e {
+ WB_WDT_TYPE_NAME = 0, /* watchdog identify */
+ WB_WDT_TYPE_STATE = 1, /* watchdog state */
+ WB_WDT_TYPE_TIMELEFT = 2, /* watchdog timeleft */
+ WB_WDT_TYPE_TIMEOUT = 3, /* watchdog timeout */
+ WB_WDT_TYPE_ENABLE = 4, /* watchdog enable */
+} wb_wdt_type_t;
+
+/* Port Power Status */
+typedef enum wb_port_power_status_e {
+ WB_PORT_POWER_OFF = 0, /* port power off */
+ WB_PORT_POWER_ON = 1, /* port power on */
+} wb_port_power_status_t;
+
+/* sensor monitor or not */
+typedef enum wb_sensor_monitor_flag_e {
+ WB_SENSOR_MONITOR_NO = 0, /* sensor not monitor */
+ WB_SENSOR_MONITOR_YES = 1, /* sensor monitor */
+} wb_sensor_monitor_flag_t;
+
+typedef enum dfd_dev_info_type_e {
+ DFD_DEV_INFO_TYPE_MAC = 1,
+ DFD_DEV_INFO_TYPE_NAME = 2,
+ DFD_DEV_INFO_TYPE_SN = 3,
+ DFD_DEV_INFO_TYPE_PWR_CONS = 4,
+ DFD_DEV_INFO_TYPE_HW_INFO = 5,
+ DFD_DEV_INFO_TYPE_DEV_TYPE = 6,
+ DFD_DEV_INFO_TYPE_PART_NAME = 7,
+ DFD_DEV_INFO_TYPE_PART_NUMBER = 8, /* part number */
+ DFD_DEV_INFO_TYPE_FAN_DIRECTION = 9,
+ DFD_DEV_INFO_TYPE_MAX_OUTPUT_POWRER = 10, /* max_output_power */
+ DFD_DEV_INFO_TYPE_SPEED_CAL = 11,
+ DFD_DEV_INFO_TYPE_ASSET_TAG = 12,
+ DFD_DEV_INFO_TYPE_VENDOR = 13,
+} dfd_dev_tlv_type_t;
+
+/* Master device type */
+typedef enum wb_main_dev_type_e {
+ WB_MAIN_DEV_MAINBOARD = 0, /* Main board */
+ WB_MAIN_DEV_FAN = 1, /* FAN */
+ WB_MAIN_DEV_PSU = 2, /* PSU */
+ WB_MAIN_DEV_SFF = 3, /* Optical module */
+ WB_MAIN_DEV_CPLD = 4, /* CPLD */
+ WB_MAIN_DEV_SLOT = 5, /* Daughter card */
+} wb_main_dev_type_t;
+
+/* Subdevice type */
+typedef enum wb_minor_dev_type_e {
+ WB_MINOR_DEV_NONE = 0, /* None */
+ WB_MINOR_DEV_TEMP = 1, /* temperature*/
+ WB_MINOR_DEV_IN = 2, /* voltage */
+ WB_MINOR_DEV_CURR = 3, /* current */
+ WB_MINOR_DEV_POWER = 4, /* power */
+ WB_MINOR_DEV_MOTOR = 5, /* motor */
+ WB_MINOR_DEV_PSU = 6, /* Power supply type */
+ WB_MINOR_DEV_FAN = 7, /* Fan model */
+ WB_MINOR_DEV_CPLD = 8, /* CPLD */
+ WB_MINOR_DEV_FPGA = 9, /* FPGA */
+ WB_MINOR_DEV_EEPROM = 10, /* EEPROM */
+} wb_minor_dev_type_t;
+
+/* SENSORS attribute type */
+typedef enum wb_sensor_type_e {
+ WB_SENSOR_INPUT = 0, /* Sensor value */
+ WB_SENSOR_ALIAS = 1, /* Sensor nickname */
+ WB_SENSOR_TYPE = 2, /* Sensor type*/
+ WB_SENSOR_MAX = 3, /* Sensor maximum */
+ WB_SENSOR_MAX_HYST = 4, /* Sensor hysteresis value */
+ WB_SENSOR_MIN = 5, /* Sensor minimum */
+ WB_SENSOR_CRIT = 6, /* Sensor crit value */
+ WB_SENSOR_RANGE = 7, /* Sensor error value */
+ WB_SENSOR_NOMINAL_VAL = 8, /* Nominal value of the sensor */
+ WB_SENSOR_HIGH = 9, /* Sensor height */
+ WB_SENSOR_LOW = 10, /* Sensor low */
+} wb_sensor_type_t;
+
+/* sff cpld attribute type */
+typedef enum wb_sff_cpld_attr_e {
+ WB_SFF_POWER_ON = 0x01,
+ WB_SFF_TX_FAULT,
+ WB_SFF_TX_DIS,
+ WB_SFF_PRESENT_RESERVED,
+ WB_SFF_RX_LOS,
+ WB_SFF_RESET,
+ WB_SFF_LPMODE,
+ WB_SFF_MODULE_PRESENT,
+ WB_SFF_INTERRUPT,
+} wb_sff_cpld_attr_t;
+
+/* LED attribute type */
+typedef enum wb_led_e {
+ WB_SYS_LED_FRONT = 0, /* Front panel SYS light */
+ WB_SYS_LED_REAR = 1, /* SYS light on rear panel */
+ WB_BMC_LED_FRONT = 2, /* BMC indicator on the front panel */
+ WB_BMC_LED_REAR = 3, /* BMC indicator on the rear panel */
+ WB_FAN_LED_FRONT = 4, /* Front panel fan light */
+ WB_FAN_LED_REAR = 5, /* Rear panel fan light */
+ WB_PSU_LED_FRONT = 6, /* Front panel power light */
+ WB_PSU_LED_REAR = 7, /* Rear panel power light */
+ WB_ID_LED_FRONT = 8, /* Front panel positioning light */
+ WB_ID_LED_REAR = 9, /* Rear panel positioning light */
+ WB_FAN_LED_MODULE = 10, /* Fan module indicator */
+ WB_PSU_LED_MODULE = 11, /* Power module indicator */
+ WB_SLOT_LED_MODULE = 12, /* Sub-card status indicator */
+} wb_led_t;
+
+extern int g_dfd_dbg_level;
+extern int g_dfd_fan_dbg_level;
+extern int g_dfd_fru_dbg_level;
+extern int g_dfd_eeprom_dbg_level;
+extern int g_dfd_cpld_dbg_level;
+extern int g_dfd_fpga_dbg_level;
+extern int g_dfd_sysled_dbg_level;
+extern int g_dfd_slot_dbg_level;
+extern int g_dfd_sensor_dbg_level;
+extern int g_dfd_psu_dbg_level;
+extern int g_dfd_sff_dbg_level;
+extern int g_dfd_watchdog_dbg_level;
+extern int g_dfd_custom_dbg_level;
+
+#define WB_MIN(a, b) ((a) < (b) ? (a) : (b))
+#define WB_MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define DBG_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DFD_FAN_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_fan_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DBG_FRU_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_fru_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DBG_EEPROM_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_eeprom_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DBG_CPLD_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_cpld_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DBG_FPGA_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_fpga_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DBG_SYSLED_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_sysled_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DFD_SLOT_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_slot_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DFD_SENSOR_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_sensor_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DFD_PSU_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_psu_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DFD_SFF_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_sff_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DFD_WDT_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_watchdog_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+#define DFD_SYSTEM_DEBUG(level, fmt, arg...) do { \
+ if (g_dfd_custom_dbg_level & level) { \
+ if (level >= DBG_ERROR) { \
+ printk(KERN_ERR "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } else { \
+ printk(KERN_INFO "[DBG-%d]:<%s, %d>:"fmt, level, __FUNCTION__, __LINE__, ##arg); \
+ } \
+ } \
+} while (0)
+
+/**
+ * wb_dev_cfg_init - dfd module initialization
+ *
+ * @returns: <0 Failed, otherwise succeeded
+ */
+int32_t wb_dev_cfg_init(void);
+
+/**
+ * wb_dev_cfg_exit - dfd module exit
+ *
+ * @returns: void
+ */
+
+void wb_dev_cfg_exit(void);
+
+/**
+ * dfd_get_dev_number - Get the number of devices
+ * @main_dev_id:Master device number
+ * @minor_dev_id:Secondary device number
+ * @returns: <0 failed, otherwise number of devices is returned
+ */
+int dfd_get_dev_number(unsigned int main_dev_id, unsigned int minor_dev_id);
+#endif /* _WB_MODULE_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_psu_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_psu_driver.h
new file mode 100644
index 000000000000..5de93f46bd11
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_psu_driver.h
@@ -0,0 +1,114 @@
+/*
+ * A header definition for wb_psu_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_PSU_DRIVER_H_
+#define _WB_PSU_DRIVER_H_
+
+/**
+ * dfd_get_psu_info - Get Power Information
+ * @index: Number of the power supply, starting from 1
+ * @cmd: Power supply information Type, power supply name :2, power supply serial number :3, power supply hardware version :5
+ * @buf: Receive buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_psu_info(unsigned int psu_index, uint8_t cmd, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_present_status_str - Get Power status
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_present_status_str(unsigned int psu_index, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_out_status_str - Get the output power status
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_out_status_str(unsigned int psu_index, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_status_pmbus_str - Gets the value on the pmbus register of the power supply
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_status_pmbus_str(unsigned int psu_index, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_in_status_str - Get the input power status
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_in_status_str(unsigned int psu_index, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_input_type - Get the power input type
+ * @index: Number of the power supply, starting from 1
+ * @buf: Receive buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_psu_input_type(unsigned int psu_index, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_alarm_status - Get power PMBUS WORD STATUS status
+ * @index: Number of the power supply, starting from 1
+ * return: Success:return psu output status
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_psu_alarm_status(unsigned int psu_index, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_fan_ratio_str - Gets the target fan rotation rate
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_fan_ratio_str(unsigned int psu_index, char *buf, size_t count);
+ssize_t dfd_set_psu_fan_ratio_str(unsigned int psu_index, int pwm);
+/**
+ * dfd_get_psu_pmbus_status - Get power Status Word
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_pmbus_status(unsigned int psu_index, char *buf, size_t count);
+/**
+ * dfd_get_psu_present_status - Obtain the power supply status
+ * @index: Number of the power supply, starting from 1
+ * return: 0:Not in the position
+ * 1:position
+ * : Negative value - Read failed
+ */
+int dfd_get_psu_present_status(unsigned int psu_index);
+
+ssize_t dfd_get_psu_threshold_str(unsigned int psu_index, unsigned int type, char *buf, size_t count);
+
+ssize_t dfd_get_psu_hw_status_str(unsigned int psu_index, char *buf, size_t count);
+
+ssize_t dfd_get_psu_blackbox(unsigned int psu_index, char *buf, size_t count);
+ssize_t dfd_get_psu_pmbus(unsigned int psu_index, char *buf, size_t count);
+int dfd_clear_psu_blackbox(unsigned int psu_index, uint8_t value);
+#endif /* _WB_PSU_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_sensors_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_sensors_driver.h
new file mode 100644
index 000000000000..d33ee3217e37
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_sensors_driver.h
@@ -0,0 +1,82 @@
+/*
+ * A header definition for wb_sensors_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_SENSORS_DRIVER_H_
+#define _WB_SENSORS_DRIVER_H_
+
+/**
+ * dfd_get_temp_info - Get temperature information
+ * @main_dev_id: Motherboard :0 Power supply :2 subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1/psu1
+ * @temp_index: Temperature index, starting at 1
+ * @temp_type: Read type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_temp_info(uint8_t main_dev_id, uint8_t dev_index, uint8_t temp_index,
+ uint8_t temp_attr, char *buf, size_t count);
+
+/**
+ * dfd_get_voltage_info - Get voltage information
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1
+ * @in_index: Voltage index, starting at 1
+ * @in_type:Voltage type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_voltage_info(uint8_t main_dev_id, uint8_t dev_index, uint8_t in_index,
+ uint8_t in_attr, char *buf, size_t count);
+
+/**
+ * dfd_get_current_info - Get current information
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1
+ * @in_index: Current index, starting at 1
+ * @in_type: Current type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_current_info(uint8_t main_dev_id, uint8_t dev_index, uint8_t curr_index,
+ uint8_t curr_attr, char *buf, size_t count);
+
+/**
+ * dfd_get_psu_sensor_info - Obtain PMBUS information about the power supply
+ * @psu_index: Power index, starting at 1
+ * @sensor_type: Type of the obtained pmbus information
+ * @buf: pmbus results are stored in buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_psu_sensor_info(uint8_t psu_index, uint8_t sensor_type, char *buf, size_t count);
+
+
+/**
+ * dfd_get_main_board_monitor_flag - Get Monitor flag info
+ * @main_dev_id: Motherboard :0 Power supply :2 subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1
+ * @sensor_type: Type of the obtained pmbus information
+ * @in_type: Voltage type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+int dfd_get_main_board_monitor_flag(uint8_t main_dev_id, uint8_t dev_index, uint8_t sensor_type,
+ uint8_t sensor_index, char *buf, size_t count);
+#endif /* _WB_SENSORS_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_sff_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_sff_driver.h
new file mode 100644
index 000000000000..e26e12805de6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_sff_driver.h
@@ -0,0 +1,63 @@
+/*
+ * A header definition for wb_sff_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_SFF_DRIVER_H_
+#define _WB_SFF_DRIVER_H_
+
+/**
+ * dfd_set_sff_cpld_info - Example Set the CPLD register status of the optical module
+ * @sff_index: Optical module number, starting from 1
+ * @cpld_reg_type: Optical module CPLD register type
+ * @value: Writes the value to the register
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_set_sff_cpld_info(unsigned int sff_index, int cpld_reg_type, int value);
+
+/**
+ * dfd_get_sff_cpld_info - Obtain the CPLD register status of the optical module
+ * @sff_index: Optical module number, starting from 1
+ * @cpld_reg_type: Optical module CPLD register type
+ * @buf: Optical module E2 receives information from buf
+ * @count: buf length
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_sff_cpld_info(unsigned int sff_index, int cpld_reg_type, char *buf, size_t count);
+
+/**
+ * dfd_get_single_eth_optoe_type - get sff optoe type
+ * @sff_index: Optical module number, starting from 1
+ * @optoe_type: Optical module type
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+int dfd_get_single_eth_optoe_type(unsigned int sff_index, int *optoe_type);
+
+/**
+ * dfd_set_single_eth_optoe_type - set sff optoe type
+ * @sff_index: Optical module number, starting from 1
+ * @optoe_type: Optical module type
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+int dfd_set_single_eth_optoe_type(unsigned int sff_index, int optoe_type);
+
+#endif /* _WB_SFF_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_slot_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_slot_driver.h
new file mode 100644
index 000000000000..7978fa5b7698
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_slot_driver.h
@@ -0,0 +1,64 @@
+/*
+ * A header definition for wb_slot_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_SLOT_DRIVER_H_
+#define _WB_SLOT_DRIVER_H_
+
+/**
+ * dfd_get_slot_status_str - Gets the subcard status
+ * @slot_index: Number of the sub-card, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_slot_status_str(unsigned int slot_index, char *buf, size_t count);
+
+/**
+ * dfd_get_slot_info - Obtain the subcard information
+ * @slot_index: Number of the sub-card, starting from 1
+ * @cmd: Card information type, sub-card name :2, sub-card serial number :3, sub-card hardware version number :5
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_slot_info(unsigned int slot_index, uint8_t cmd, char *buf, size_t count);
+
+/**
+ * dfd_get_slot_power_status_str - get power status of slot
+ * @slot_index: Number of the sub-card, starting from 1
+ * @buf: Receive buf
+ * @count: Receive buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_slot_power_status_str(unsigned int slot_index, char *buf, size_t count);
+
+/**
+ * dfd_set_slot_power_status_str - set power status of slot
+ * @slot_index: Number of the sub-card, starting from 1
+ * @value: Power status of slot
+ * return: Success: 0 is returned
+ * : Failed: A negative value is returned
+ */
+int dfd_set_slot_power_status_str(unsigned int slot_index, int value);
+
+#endif /* _WB_SLOT_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_system_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_system_driver.h
new file mode 100644
index 000000000000..2298c5bb11b1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_system_driver.h
@@ -0,0 +1,33 @@
+/*
+ * A header definition for wb_system_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SYSTEM_DRIVER_H_
+#define _SYSTEM_DRIVER_H_
+
+typedef enum module_pwr_status_e {
+ MODULE_POWER_OFF = 0,
+ MODULE_POWER_ON,
+} module_pwr_status_t;
+
+ssize_t dfd_system_get_system_value(unsigned int type, int *value);
+ssize_t dfd_system_set_system_value(unsigned int type, int value);
+ssize_t dfd_system_get_port_power_status(unsigned int type, char *buf, size_t count);
+
+#endif /* _SYSTEM_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_watchdog_driver.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_watchdog_driver.h
new file mode 100644
index 000000000000..c59bd64e692a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/include/wb_watchdog_driver.h
@@ -0,0 +1,37 @@
+/*
+ * A header definition for wb_watchdog_driver driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WB_WATCHDOG_DRIVER_H_
+#define _WB_WATCHDOG_DRIVER_H_
+
+/**
+ * dfd_get_watchdog_info - Get watchdog information
+ * @type: Watchdog information type
+ * @buf: Receive buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_watchdog_info(uint8_t type, char *buf, size_t count);
+
+ssize_t dfd_watchdog_get_status_str(char *buf, size_t count);
+ssize_t dfd_watchdog_get_status(char *buf, size_t count);
+ssize_t dfd_watchdog_set_status(int value);
+
+#endif /* _WB_WATCHDOG_DRIVER_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/switch_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/switch_driver.c
new file mode 100644
index 000000000000..5628aadab430
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/switch_driver.c
@@ -0,0 +1,4577 @@
+/*
+ * An switch_driver driver for switch devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include
+
+#include "dfd_sysfs_common.h"
+#include "switch_driver.h"
+#include "wb_module.h"
+#include "wb_fan_driver.h"
+#include "wb_eeprom_driver.h"
+#include "wb_cpld_driver.h"
+#include "wb_fpga_driver.h"
+#include "wb_led_driver.h"
+#include "wb_slot_driver.h"
+#include "wb_sensors_driver.h"
+#include "wb_psu_driver.h"
+#include "wb_sff_driver.h"
+#include "wb_watchdog_driver.h"
+#include "wb_system_driver.h"
+#include "dfd_cfg.h"
+
+int g_switch_dbg_level = 0;
+
+/* change the following parameter by your switch. */
+#define MAIN_BOARD_TEMP_SENSOR_NUMBER (10)
+#define MAIN_BOARD_VOL_SENSOR_NUMBER (10)
+#define MAIN_BOARD_CURR_SENSOR_NUMBER (0)
+#define SYSEEPROM_SIZE (256)
+#define FAN_NUMBER (6)
+#define FAN_MOTOR_NUMBER (2)
+#define PSU_NUMBER (2)
+#define PSU_TEMP_SENSOR_NUMBER (3)
+#define ETH_NUMBER (32)
+#define ETH_EEPROM_SIZE (0x8180)
+#define MAIN_BOARD_FPGA_NUMBER (1)
+#define MAIN_BOARD_CPLD_NUMBER (5)
+#define SLOT_NUMBER (0)
+#define SLOT_TEMP_NUMBER (0)
+#define SLOT_VOL_NUMBER (0)
+#define SLOT_CURR_NUMBER (0)
+#define SLOT_FPGA_NUMBER (0)
+#define SLOT_CPLD_NUMBER (0)
+
+/***************************************main board temp*****************************************/
+/*
+ * dfd_get_main_board_temp_number - Used to get main board temperature sensors number,
+ *
+ * This function returns main board temperature sensors by your switch,
+ * If there is no main board temperature sensors, returns 0,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_get_main_board_temp_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_TEMP);
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_alias - Used to identify the location of the temperature sensor,
+ * such as air_inlet, air_outlet and so on.
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_alias(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, temp_index, WB_SENSOR_ALIAS,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_type - Used to get the model of temperature sensor,
+ * such as lm75, tmp411 and so on
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_type(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, temp_index, WB_SENSOR_TYPE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_max - Used to get the maximum threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_max(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, temp_index, WB_SENSOR_MAX,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_min - Used to get the minimum threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_min(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, temp_index, WB_SENSOR_MIN,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_high - Used to get the high threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_high(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, temp_index, WB_SENSOR_HIGH,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_low - Used to get the low threshold of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_low(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, temp_index, WB_SENSOR_LOW,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_value - Used to get the input value of temperature sensor
+ * filled the value to buf, the value is integer with millidegree Celsius
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_value(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, temp_index, WB_SENSOR_INPUT,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_temp_monitor_flag - Used to get monitor flag of temperature sensor
+ * filled the value to buf, the value is integer
+ * @index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_temp_monitor_flag(unsigned int index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_main_board_monitor_flag(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, WB_MINOR_DEV_TEMP, index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+/***********************************end of main board temp*************************************/
+
+/*************************************main board voltage***************************************/
+static int dfd_get_main_board_vol_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_IN);
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_alias - Used to identify the location of the voltage sensor,
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_alias(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, vol_index, WB_SENSOR_ALIAS,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_type - Used to get the model of voltage sensor,
+ * such as udc90160, tps53622 and so on
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_type(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, vol_index, WB_SENSOR_TYPE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_max - Used to get the maximum threshold of voltage sensor
+ * filled the value to buf, the value is integer with mV
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_max(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, vol_index, WB_SENSOR_MAX,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_min - Used to get the minimum threshold of voltage sensor
+ * filled the value to buf, the value is integer with mV
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_min(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, vol_index, WB_SENSOR_MIN,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_range - Used to get the output error value of voltage sensor
+ * filled the value to buf
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_range(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, vol_index,
+ WB_SENSOR_RANGE, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_nominal_value - Used to get the nominal value of voltage sensor
+ * filled the value to buf
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_nominal_value(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, vol_index,
+ WB_SENSOR_NOMINAL_VAL, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_value - Used to get the input value of voltage sensor
+ * filled the value to buf, the value is integer with mV
+ * @vol_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_value(unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, vol_index, WB_SENSOR_INPUT,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_vol_monitor_flag - Used to get monitor flag of voltage sensor
+ * filled the value to buf, the value is integer
+ * @temp_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_vol_monitor_flag(unsigned int temp_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_main_board_monitor_flag(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, WB_MINOR_DEV_IN, temp_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+/*********************************end of main board voltage************************************/
+/*************************************main board current***************************************/
+static int dfd_get_main_board_curr_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_CURR);
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_curr_alias - Used to identify the location of the current sensor,
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_curr_alias(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, curr_index, WB_SENSOR_ALIAS,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_curr_type - Used to get the model of current sensor,
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_curr_type(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, curr_index, WB_SENSOR_TYPE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_curr_max - Used to get the maximum threshold of current sensor
+ * filled the value to buf, the value is integer with mA
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_curr_max(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, curr_index, WB_SENSOR_MAX,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_curr_min - Used to get the minimum threshold of current sensor
+ * filled the value to buf, the value is integer with mA
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_curr_min(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, curr_index, WB_SENSOR_MIN,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_curr_value - Used to get the input value of current sensor
+ * filled the value to buf, the value is integer with mA
+ * @curr_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_curr_value(unsigned int curr_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, curr_index, WB_SENSOR_INPUT,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_curr_monitor_flag - Used to get monitor flag of current sensor
+ * filled the value to buf, the value is integer
+ * @index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_curr_monitor_flag(unsigned int index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_main_board_monitor_flag(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_NONE, WB_MINOR_DEV_CURR, index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+/*********************************end of main board current************************************/
+
+/*****************************************syseeprom*******************************************/
+/*
+ * dfd_get_syseeprom_size - Used to get syseeprom size
+ *
+ * This function returns the size of syseeprom by your switch,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_get_syseeprom_size(void)
+{
+ int ret;
+
+ ret = dfd_get_eeprom_size(WB_MAIN_DEV_MAINBOARD, 0);
+ return ret;
+}
+
+/*
+ * dfd_read_syseeprom_data - Used to read syseeprom data,
+ * @buf: Data read buffer
+ * @offset: offset address to read syseeprom data
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_read_syseeprom_data(char *buf, loff_t offset, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_read_eeprom_data(WB_MAIN_DEV_MAINBOARD, 0, buf, offset, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_write_syseeprom_data - Used to write syseeprom data
+ * @buf: Data write buffer
+ * @offset: offset address to write syseeprom data
+ * @count: length of buf
+ *
+ * This function returns the written length of syseeprom,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_write_syseeprom_data(char *buf, loff_t offset, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_write_eeprom_data(WB_MAIN_DEV_MAINBOARD, 0, buf, offset, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+/*************************************end of syseeprom****************************************/
+
+/********************************************fan**********************************************/
+static int dfd_get_fan_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_FAN, WB_MINOR_DEV_NONE);
+ return ret;
+}
+
+/*
+ * dfd_get_fan_status - Used to get fan status,
+ * filled the value to buf, fan status define see enum status_e
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_status(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fan_status_str(fan_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_present - Used to get fan present status,
+ * filled the value to buf, fan status define see enum status_e
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_present(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fan_present_str(fan_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static int dfd_get_fan_motor_number(unsigned int fan_index)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_FAN, WB_MINOR_DEV_MOTOR);
+ return ret;
+}
+
+/*
+ * dfd_get_fan_model_name - Used to get fan model name,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_model_name(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_info(fan_index, DFD_DEV_INFO_TYPE_NAME, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_vendor - Used to get fan vendor,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_vendor(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_info(fan_index, DFD_DEV_INFO_TYPE_VENDOR, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_serial_number - Used to get fan serial number,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_serial_number(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_info(fan_index, DFD_DEV_INFO_TYPE_SN, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_part_number - Used to get fan part number,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_part_number(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_info(fan_index, DFD_DEV_INFO_TYPE_PART_NUMBER, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_hardware_version - Used to get fan hardware version,
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_hardware_version(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_info(fan_index, DFD_DEV_INFO_TYPE_HW_INFO, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_led_status - Used to get fan led status
+ * filled the value to buf, led status value define see enum fan_status_e
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_led_status(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_led_status(WB_FAN_LED_MODULE, fan_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_fan_led_status - Used to set fan led status
+ * @fan_index: start with 1
+ * @status: led status, led status value define see enum led_status_e
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_fan_led_status(unsigned int fan_index, int status)
+{
+ int ret;
+
+ ret = dfd_set_led_status(WB_FAN_LED_MODULE, fan_index, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_direction - Used to get fan air flow direction,
+ * filled the value to buf, air flow direction define see enum air_flow_direction_e
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_direction(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_direction_str(fan_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_motor_status - Used to get fan motor status
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_motor_status(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fan_motor_status_str(fan_index, motor_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_motor_speed - Used to get fan motor speed
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_motor_speed(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fan_speed_str(fan_index, motor_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_motor_speed_tolerance - Used to get fan motor speed tolerance
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_motor_speed_tolerance(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_motor_speed_tolerance_str(fan_index, motor_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_motor_speed_target - Used to get fan motor speed target
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_motor_speed_target(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_motor_speed_target_str(fan_index, motor_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_motor_speed_max - Used to get the maximum threshold of fan motor
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_motor_speed_max(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_motor_speed_max_str(fan_index, motor_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_motor_speed_min - Used to get the minimum threshold of fan motor
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @motor_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_motor_speed_min(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_fan_present_status(fan_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_fan_motor_speed_min_str(fan_index, motor_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_fan_ratio - Used to get the ratio of fan
+ * filled the value to buf
+ * @fan_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_fan_ratio(unsigned int fan_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fan_pwm_str(fan_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_fan_ratio - Used to set the ratio of fan
+ * @fan_index: start with 1
+ * @ratio: motor speed ratio, from 0 to 100
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_fan_ratio(unsigned int fan_index, int ratio)
+{
+ int ret;
+
+ /* add vendor codes here */
+ ret = dfd_set_fan_pwm(fan_index, ratio);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+/****************************************end of fan*******************************************/
+/********************************************psu**********************************************/
+static int dfd_get_psu_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_PSU, WB_MINOR_DEV_NONE);
+ return ret;
+}
+
+/*
+ * dfd_get_psu_present_status - Used to get psu present status
+ * filled the value to buf, psu present status define see enum psu_status_e
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_present(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_psu_present_status_str(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static int dfd_get_psu_temp_number(unsigned int psu_index)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_PSU, WB_MINOR_DEV_TEMP);
+ return ret;
+}
+
+/* Similar to dfd_get_psu_model_name */
+static ssize_t dfd_get_psu_model_name(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_PART_NAME, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_vendor(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_VENDOR, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_date(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_ASSET_TAG, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status_word;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ status = status | 0x01;
+ return (ssize_t)snprintf(buf, count, "0x%x\n", status);
+ }
+
+ ret = dfd_get_psu_pmbus_status(psu_index, buf, count);
+ if (ret < 0) {
+ SWITCH_DEBUG(DBG_ERROR, "get psu pmbus status error, ret: %ld, psu_index: %u\n", ret, psu_index);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ } else {
+ ret = kstrtoint(buf, 0, &status_word);
+ if (ret) {
+ SWITCH_DEBUG(DBG_ERROR, "invalid value: %s \n", buf);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ status = 0;
+ mem_clear(buf, count);
+ if (status_word < 0) {
+ return status_word;
+ } else {
+ status = (status_word & PSU_OFF_FAULT) ? (status | 0x02) : status;
+ status = (status_word & PSU_FAN_FAULT) ? (status | 0x04) : status;
+ status = (status_word & PSU_VOUT_FAULT) ? (status | 0x08) : status;
+ status = (status_word & PSU_IOUT_FAULT) ? (status | 0x10) : status;
+ status = (status_word & PSU_INPUT_FAULT) ? (status | 0x20) : status;
+ status = (status_word & PSU_TEMP_FAULT) ? (status | 0x40) : status;
+ }
+ return (ssize_t)snprintf(buf, count, "0x%x\n", status);
+}
+
+static ssize_t dfd_get_psu_alarm(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_alarm_status(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to wb_get_fan_serial_number */
+static ssize_t dfd_get_psu_serial_number(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_SN, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to wb_get_fan_part_number */
+static ssize_t dfd_get_psu_part_number(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_PART_NUMBER, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to wb_get_fan_hardware_version */
+static ssize_t dfd_get_psu_hardware_version(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_HW_INFO, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_type - Used to get the input type of psu
+ * filled the value to buf, input type value define see enum psu_input_type_e
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_type(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_input_type(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_in_curr - Used to get the input current of psu
+ * filled the value to buf, the value is integer with mA
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_in_curr(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_sensor_info(psu_index, PSU_IN_CURR, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_in_vol - Used to get the input voltage of psu
+ * filled the value to buf, the value is integer with mV
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_in_vol(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_sensor_info(psu_index, PSU_IN_VOL, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_in_power - Used to get the input power of psu
+ * filled the value to buf, the value is integer with uW
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_in_power(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_sensor_info(psu_index, PSU_IN_POWER, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_out_curr - Used to get the output current of psu
+ * filled the value to buf, the value is integer with mA
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_out_curr(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_sensor_info(psu_index, PSU_OUT_CURR, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_out_vol - Used to get the output voltage of psu
+ * filled the value to buf, the value is integer with mV
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_out_vol(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_sensor_info(psu_index, PSU_OUT_VOL, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_out_power - Used to get the output power of psu
+ * filled the value to buf, the value is integer with uW
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_out_power(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_sensor_info(psu_index, PSU_OUT_POWER, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_out_max_power - Used to get the output max power of psu
+ * filled the value to buf, the value is integer with uW
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_out_max_power(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_MAX_OUTPUT_POWRER, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_in_status - Used to get psu input status
+ * filled the value to buf, psu input status define see enum psu_io_status_e
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_in_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_in_status_str(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_out_status - Used to get psu output status
+ * filled the value to buf, psu output status define see enum psu_io_status_e
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_out_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_out_status_str(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_hw_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_psu_hw_status_str(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_attr_threshold(unsigned int psu_index, unsigned int type, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_psu_threshold_str(psu_index, type, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_status_pmbus(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_status_pmbus_str(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_fan_speed - Used to get psu fan speed
+ * filled the value to buf
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_fan_speed(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_sensor_info(psu_index, PSU_FAN_SPEED, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_fan_ratio - Used to get the ratio of psu fan
+ * filled the value to buf
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_fan_ratio(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_fan_ratio_str(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_psu_fan_ratio - Used to set the ratio of psu fan
+ * @psu_index: start with 1
+ * @ratio: from 0 to 100
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_psu_fan_ratio(unsigned int psu_index, int ratio)
+{
+ /* add vendor codes here */
+ return -WB_SYSFS_RV_UNSUPPORT;
+}
+
+/*
+ * dfd_get_psu_fan_direction - Used to get psu air flow direction,
+ * filled the value to buf, air flow direction define enum air_flow_direction_e
+ * @psu_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_psu_fan_direction(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_FAN_DIRECTION, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_fan_led_status */
+static ssize_t dfd_get_psu_led_status(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status_word;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ status = LED_STATUS_DARK; /* led off */
+ return (ssize_t)snprintf(buf, count, "%d\n", status);
+ }
+ status = LED_STATUS_GREEN;
+
+ ret = dfd_get_psu_pmbus_status(psu_index, buf, count);
+ if (ret < 0) {
+ SWITCH_DEBUG(DBG_ERROR, "get psu pmbus status error, ret: %ld, psu_index: %u\n", ret, psu_index);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ } else {
+ ret = kstrtoint(buf, 0, &status_word);
+ if (ret) {
+ SWITCH_DEBUG(DBG_ERROR, "invalid value: %s \n", buf);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ mem_clear(buf, count);
+ if (status_word > 0) {
+ status = LED_STATUS_YELLOW; /* led amber */
+ return (ssize_t)snprintf(buf, count, "%d\n", status);
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", status); /* led green */
+}
+
+static ssize_t dfd_get_psu_fan_speed_cal(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_info(psu_index, DFD_DEV_INFO_TYPE_SPEED_CAL, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_temp_alias */
+static ssize_t dfd_get_psu_temp_alias(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_PSU, psu_index, temp_index, WB_SENSOR_ALIAS,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_temp_type */
+static ssize_t dfd_get_psu_temp_type(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_PSU, psu_index, temp_index, WB_SENSOR_TYPE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+
+}
+
+/* Similar to dfd_get_main_board_temp_max */
+static ssize_t dfd_get_psu_temp_max(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_PSU, psu_index, temp_index, WB_SENSOR_MAX,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_main_board_temp_max */
+static int dfd_set_psu_temp_max(unsigned int psu_index, unsigned int temp_index,
+ const char *buf, size_t count)
+{
+ /* add vendor codes here */
+ return -WB_SYSFS_RV_UNSUPPORT;
+}
+
+/* Similar to dfd_get_main_board_temp_min */
+static ssize_t dfd_get_psu_temp_min(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_PSU, psu_index, temp_index, WB_SENSOR_MIN,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_main_board_temp_min */
+static int dfd_set_psu_temp_min(unsigned int psu_index, unsigned int temp_index,
+ const char *buf, size_t count)
+{
+ /* add vendor codes here */
+ return -WB_SYSFS_RV_UNSUPPORT;
+}
+
+/* Similar to dfd_get_main_board_temp_value */
+static ssize_t dfd_get_psu_temp_value(unsigned int psu_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_PSU, psu_index, temp_index, WB_SENSOR_INPUT,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_psu_eeprom_size - Used to get psu eeprom size
+ *
+ * This function returns the size of psu eeprom,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_get_psu_eeprom_size(unsigned int psu_index)
+{
+ int ret;
+
+ ret = dfd_get_eeprom_size(WB_MAIN_DEV_PSU, psu_index);
+ return ret;
+}
+
+/*
+ * dfd_read_psu_eeprom_data - Used to read psu eeprom data,
+ * @buf: Data read buffer
+ * @offset: offset address to read psu eeprom data
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_read_psu_eeprom_data(unsigned int psu_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_read_eeprom_data(WB_MAIN_DEV_PSU, psu_index, buf, offset, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_blackbox_info(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_blackbox(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_psu_pmbus_info(unsigned int psu_index, char *buf, size_t count)
+{
+ ssize_t ret;
+ int status;
+
+ status = dfd_get_psu_present_status(psu_index);
+ if (status == DEV_ABSENT) {
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ }
+
+ ret = dfd_get_psu_pmbus(psu_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_clear_psu_blackbox_info - Used to clear psu blackbox information
+ * @psu_index: start with 1
+ * @value: 1
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_clear_psu_blackbox_info(unsigned int psu_index, uint8_t value)
+{
+ int ret;
+
+ ret = dfd_clear_psu_blackbox(psu_index, value);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+
+}
+/****************************************end of psu*******************************************/
+/****************************************transceiver******************************************/
+static int dfd_get_eth_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_SFF, WB_MINOR_DEV_NONE);
+ return ret;
+}
+
+/*
+ * dfd_get_transceiver_power_on_status - Used to get the whole machine port power on status,
+ * filled the value to buf, 0: power off, 1: power on
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_transceiver_power_on_status(char *buf, size_t count)
+{
+ ssize_t ret;
+ unsigned int eth_index, eth_num;
+ int len, left_len;
+ eth_num = dfd_get_dev_number(WB_MAIN_DEV_SFF, WB_MINOR_DEV_NONE);
+ if (eth_num <= 0) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+
+ mem_clear(buf, count);
+ len = 0;
+ left_len = count - 1;
+
+ for (eth_index = 1; eth_index <= eth_num; eth_index++) {
+ SWITCH_DEBUG(DBG_VERBOSE, "eth index: %u\n", eth_index);
+ if (left_len > 0) {
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_POWER_ON, buf, left_len);
+ if (ret < 0) {
+ SWITCH_DEBUG(DBG_ERROR, "get eth%u power status failed, ret: %ld\n", eth_index, ret);
+ break;
+ }
+ } else {
+ SWITCH_DEBUG(DBG_ERROR, "error: get_transceiver_power_on_status are not enough buffers.\n");
+ ret = -DFD_RV_NO_MEMORY;
+ break;
+ }
+ dfd_ko_cfg_del_lf_cr(buf); /* del '\n' */
+ len = strlen(buf);
+ left_len = count - len - 2; /* Reserve end to add '\n' and '\0' */
+ }
+
+ if (ret < 0) {
+ mem_clear(buf, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ len = strlen(buf);
+ if (len >= count) {
+ SWITCH_DEBUG(DBG_ERROR, "error: get_transceiver_power_on_status buffers too long, need: %ld, act: %d.\n", count, len);
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ buf[len] = '\n';
+ ret = strlen(buf);
+ SWITCH_DEBUG(DBG_VERBOSE, "get_transceiver_power_on_status ok. sff num:%d, len:%ld\n", eth_num, ret);
+
+ return ret;
+}
+
+/*
+ * dfd_set_transceiver_power_on_status - Used to set the whole machine port power on status,
+ * @status: power on status, 0: power off, 1: power on
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_transceiver_power_on_status(int status)
+{
+ int ret;
+
+ ret = dfd_set_sff_cpld_info(0, WB_SFF_POWER_ON, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_transceiver_present_status - Used to get the whole machine port present status,
+ * filled the value to buf, 0: absent, 1: present
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_transceiver_present_status(char *buf, size_t count)
+{
+ ssize_t ret;
+ unsigned int eth_index, eth_num;
+ int len, left_len;
+
+ eth_num = dfd_get_dev_number(WB_MAIN_DEV_SFF, WB_MINOR_DEV_NONE);
+ if (eth_num <= 0) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+
+ mem_clear(buf, count);
+ len = 0;
+ left_len = count - 1;
+
+ for (eth_index = 1; eth_index <= eth_num; eth_index++) {
+ SWITCH_DEBUG(DBG_VERBOSE, "eth index: %u\n", eth_index);
+ if (left_len > 0) {
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_MODULE_PRESENT, buf + len, left_len);
+ if (ret < 0) {
+ SWITCH_DEBUG(DBG_ERROR, "get eth%u present status failed, ret: %ld\n", eth_index, ret);
+ break;
+ }
+ } else {
+ SWITCH_DEBUG(DBG_ERROR, "error: get_transceiver_present_status are not enough buffers.\n");
+ ret = -DFD_RV_NO_MEMORY;
+ break;
+ }
+ dfd_ko_cfg_del_lf_cr(buf); /* del '\n' */
+ len = strlen(buf);
+ left_len = count - len - 2; /* Reserve end to add '\n' and '\0' */
+ }
+
+ if (ret < 0) {
+ mem_clear(buf, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ len = strlen(buf);
+ if (len >= count) {
+ SWITCH_DEBUG(DBG_ERROR, "error: get_transceiver_present_status buffers too long, need: %ld, act: %d.\n", count, len);
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ buf[len] = '\n';
+ ret = strlen(buf);
+ SWITCH_DEBUG(DBG_VERBOSE, "get_transceiver_present_status ok. sff num:%d, len:%ld\n", eth_num, ret);
+
+ return ret;
+}
+
+
+/*
+ * dfd_get_eth_power_on_status - Used to get single port power on status,
+ * filled the value to buf, 0: power off, 1: power on
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_power_on_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_POWER_ON, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_eth_power_on_status - Used to set single port power on status,
+ * @eth_index: start with 1
+ * @status: power on status, 0: power off, 1: power on
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_eth_power_on_status(unsigned int eth_index, int status)
+{
+ int ret;
+
+ ret = dfd_set_sff_cpld_info(eth_index, WB_SFF_POWER_ON, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_eth_tx_fault_status - Used to get port tx_fault status,
+ * filled the value to buf, 0: normal, 1: abnormal
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_tx_fault_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_TX_FAULT, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_eth_tx_disable_status - Used to get port tx_disable status,
+ * filled the value to buf, 0: tx_enable, 1: tx_disable
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_tx_disable_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_TX_DIS, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_eth_tx_disable_status - Used to set port tx_disable status,
+ * @eth_index: start with 1
+ * @status: tx_disable status, 0: tx_enable, 1: tx_disable
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_eth_tx_disable_status(unsigned int eth_index, int status)
+{
+ int ret;
+
+ ret = dfd_set_sff_cpld_info(eth_index, WB_SFF_TX_DIS, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_eth_present_status - Used to get port present status,
+ * filled the value to buf, 1: present, 0: absent
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_present_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_MODULE_PRESENT, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_eth_rx_los_status - Used to get port rx_los status,
+ * filled the value to buf, 0: normal, 1: abnormal
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_rx_los_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_RX_LOS, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_eth_reset_status - Used to get port reset status,
+ * filled the value to buf, 0: unreset, 1: reset
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_reset_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_RESET, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_eth_reset_status - Used to set port reset status,
+ * @eth_index: start with 1
+ * @status: reset status, 0: unreset, 1: reset
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_eth_reset_status(unsigned int eth_index, int status)
+{
+ int ret;
+
+ ret = dfd_set_sff_cpld_info(eth_index, WB_SFF_RESET, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/**
+ * dfd_get_eth_optoe_type - get sff optoe type
+ * @sff_index: Optical module number, starting from 1
+ * @optoe_type: Optical module type
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+static ssize_t dfd_get_eth_optoe_type(unsigned int eth_index, int *optoe_type, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_single_eth_optoe_type(eth_index, optoe_type);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", *optoe_type);
+}
+
+/**
+ * dfd_set_eth_optoe_type - set sff optoe type
+ * @sff_index: Optical module number, starting from 1
+ * @optoe_type: Optical module type
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+static int dfd_set_eth_optoe_type(unsigned int eth_index, int optoe_type)
+{
+ int ret;
+
+ ret = dfd_set_single_eth_optoe_type(eth_index, optoe_type);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+
+/*
+ * dfd_get_eth_low_power_mode_status - Used to get port low power mode status,
+ * filled the value to buf, 0: high power mode, 1: low power mode
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_low_power_mode_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_LPMODE, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_eth_interrupt_status - Used to get port interruption status,
+ * filled the value to buf, 0: no interruption, 1: interruption
+ * @eth_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_eth_interrupt_status(unsigned int eth_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_sff_cpld_info(eth_index, WB_SFF_INTERRUPT, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_eth_eeprom_size - Used to get port eeprom size
+ *
+ * This function returns the size of port eeprom,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_get_eth_eeprom_size(unsigned int eth_index)
+{
+ int ret;
+
+ ret = dfd_get_eeprom_size(WB_MAIN_DEV_SFF, eth_index);
+ return ret;
+}
+
+/*
+ * dfd_read_eth_eeprom_data - Used to read port eeprom data,
+ * @buf: Data read buffer
+ * @offset: offset address to read port eeprom data
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_read_eth_eeprom_data(unsigned int eth_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_read_eeprom_data(WB_MAIN_DEV_SFF, eth_index, buf, offset, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_write_eth_eeprom_data - Used to write port eeprom data
+ * @buf: Data write buffer
+ * @offset: offset address to write port eeprom data
+ * @count: length of buf
+ *
+ * This function returns the written length of port eeprom,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_write_eth_eeprom_data(unsigned int eth_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_write_eeprom_data(WB_MAIN_DEV_SFF, eth_index, buf, offset, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+/************************************end of transceiver***************************************/
+/*****************************************sysled**********************************************/
+/*
+ * dfd_get_sys_led_status - Used to get sys led status
+ * filled the value to buf, led status value define see enum fan_status_e
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_sys_led_status(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_led_status(WB_SYS_LED_FRONT, WB_MINOR_DEV_NONE, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_sys_led_status - Used to set sys led status
+ * @status: led status, led status value define see enum led_status_e
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_sys_led_status(int status)
+{
+ int ret;
+
+ ret = dfd_set_led_status(WB_SYS_LED_FRONT, WB_MINOR_DEV_NONE, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_sys_led_status */
+static ssize_t dfd_get_bmc_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ ret = dfd_get_led_status(WB_BMC_LED_FRONT, WB_MINOR_DEV_NONE, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_sys_led_status */
+static int dfd_set_bmc_led_status(int status)
+{
+ int ret;
+
+ ret = dfd_set_led_status(WB_BMC_LED_FRONT, WB_MINOR_DEV_NONE, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_sys_led_status */
+static ssize_t dfd_get_sys_fan_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ ret = dfd_get_led_status(WB_FAN_LED_FRONT, WB_MINOR_DEV_NONE, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_sys_led_status */
+static int dfd_set_sys_fan_led_status(int status)
+{
+ int ret;
+
+ ret = dfd_set_led_status(WB_FAN_LED_FRONT, WB_MINOR_DEV_NONE, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_sys_led_status */
+static ssize_t dfd_get_sys_psu_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ ret = dfd_get_led_status(WB_PSU_LED_FRONT, WB_MINOR_DEV_NONE, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_sys_led_status */
+static int dfd_set_sys_psu_led_status(int status)
+{
+ int ret;
+
+ ret = dfd_set_led_status(WB_PSU_LED_FRONT, WB_MINOR_DEV_NONE, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_sys_led_status */
+static ssize_t dfd_get_id_led_status(char *buf, size_t count)
+{
+ int ret;
+
+ ret = dfd_get_led_status(WB_ID_LED_FRONT, WB_MINOR_DEV_NONE, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_sys_led_status */
+static int dfd_set_id_led_status(int status)
+{
+ int ret;
+
+ ret = dfd_set_led_status(WB_ID_LED_FRONT, WB_MINOR_DEV_NONE, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/**************************************end of sysled******************************************/
+/******************************************FPGA***********************************************/
+static int dfd_get_main_board_fpga_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_FPGA);
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_fpga_alias - Used to identify the location of fpga,
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_fpga_alias(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_name(WB_MAIN_DEV_MAINBOARD, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_fpga_type - Used to get fpga model name
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_fpga_type(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_type(WB_MAIN_DEV_MAINBOARD, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_fpga_firmware_version - Used to get fpga firmware version,
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_fpga_firmware_version(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_fw_version(WB_MAIN_DEV_MAINBOARD, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_fpga_board_version - Used to get fpga board version,
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_fpga_board_version(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_hw_version(WB_MAIN_DEV_MAINBOARD, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_fpga_test_reg - Used to test fpga register read
+ * filled the value to buf, value is hexadecimal, start with 0x
+ * @fpga_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_fpga_test_reg(unsigned int fpga_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_testreg_str(WB_MAIN_DEV_MAINBOARD, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_main_board_fpga_test_reg - Used to test fpga register write
+ * @fpga_index: start with 1
+ * @value: value write to fpga
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_main_board_fpga_test_reg(unsigned int fpga_index, unsigned int value)
+{
+ int ret;
+
+ ret = dfd_set_fpga_testreg(WB_MAIN_DEV_MAINBOARD, fpga_index - 1, value);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+/***************************************end of FPGA*******************************************/
+/******************************************CPLD***********************************************/
+static int dfd_get_main_board_cpld_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_CPLD);
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_cpld_alias - Used to identify the location of cpld,
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_cpld_alias(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_name(WB_MAIN_DEV_MAINBOARD, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_cpld_type - Used to get cpld model name
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_cpld_type(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_type(WB_MAIN_DEV_MAINBOARD, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_cpld_firmware_version - Used to get cpld firmware version,
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_cpld_firmware_version(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_fw_version(WB_MAIN_DEV_MAINBOARD, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_cpld_board_version - Used to get cpld board version,
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_cpld_board_version(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_hw_version(WB_MAIN_DEV_MAINBOARD, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_main_board_cpld_test_reg - Used to test cpld register read
+ * filled the value to buf, value is hexadecimal, start with 0x
+ * @cpld_index: start with 1
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * if not support this attributes filled "NA" to buf,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_main_board_cpld_test_reg(unsigned int cpld_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_testreg_str(WB_MAIN_DEV_MAINBOARD, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_main_board_cpld_test_reg - Used to test cpld register write
+ * @cpld_index: start with 1
+ * @value: value write to cpld
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_main_board_cpld_test_reg(unsigned int cpld_index, unsigned int value)
+{
+ int ret;
+
+ ret = dfd_set_cpld_testreg(WB_MAIN_DEV_MAINBOARD, cpld_index - 1, value);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+/***************************************end of CPLD*******************************************/
+/****************************************watchdog*********************************************/
+/*
+ * dfd_get_watchdog_identify - Used to get watchdog identify, such as iTCO_wdt
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_watchdog_identify(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_watchdog_info(WB_WDT_TYPE_NAME, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_watchdog_timeleft - Used to get watchdog timeleft,
+ * filled the value to buf
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_watchdog_timeleft(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_watchdog_info(WB_WDT_TYPE_TIMELEFT, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_watchdog_timeout - Used to get watchdog timeout,
+ * filled the value to buf
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_watchdog_timeout(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_watchdog_info(WB_WDT_TYPE_TIMEOUT, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_watchdog_timeout - Used to set watchdog timeout,
+ * @value: timeout value
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_watchdog_timeout(int value)
+{
+ /* add vendor codes here */
+ return -WB_SYSFS_RV_UNSUPPORT;
+}
+
+/*
+ * dfd_get_watchdog_enable_status - Used to get watchdog enable status,
+ * filled the value to buf, 0: disable, 1: enable
+ * @buf: Data receiving buffer
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_watchdog_enable_status(char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_watchdog_get_status(buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_watchdog_enable_status - Used to set watchdog enable status,
+ * @value: enable status value, 0: disable, 1: enable
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_watchdog_enable_status(int value)
+{
+ /* add vendor codes here */
+ int ret;
+ ret = dfd_watchdog_set_status(value);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_set_watchdog_reset - Used to feed watchdog,
+ * @value: any value to feed watchdog
+ *
+ * This function returns 0 on success,
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_set_watchdog_reset(int value)
+{
+ /* add vendor codes here */
+ return -WB_SYSFS_RV_UNSUPPORT;
+}
+/*************************************end of watchdog*****************************************/
+/******************************************slot***********************************************/
+static int dfd_get_slot_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_SLOT, WB_MINOR_DEV_NONE);
+ return ret;
+}
+
+static int dfd_get_slot_temp_number(unsigned int slot_index)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_SLOT, WB_MINOR_DEV_TEMP);
+ return ret;
+}
+
+static int dfd_get_slot_vol_number(unsigned int slot_index)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_SLOT, WB_MINOR_DEV_IN);
+ return ret;
+}
+
+static int dfd_get_slot_curr_number(unsigned int slot_index)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_SLOT, WB_MINOR_DEV_CURR);
+ return ret;
+}
+
+static int dfd_get_slot_fpga_number(unsigned int slot_index)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_SLOT, WB_MINOR_DEV_FPGA);
+ return ret;
+}
+
+static int dfd_get_slot_cpld_number(unsigned int slot_index)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_SLOT, WB_MINOR_DEV_CPLD);
+ return ret;
+}
+
+/* Similar to dfd_get_fan_model_name */
+static ssize_t dfd_get_slot_model_name(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_slot_info(slot_index, DFD_DEV_INFO_TYPE_NAME, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_slot_vendor(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_slot_info(slot_index, DFD_DEV_INFO_TYPE_VENDOR, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to wb_get_fan_serial_number */
+static ssize_t dfd_get_slot_serial_number(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_slot_info(slot_index, DFD_DEV_INFO_TYPE_SN, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to wb_get_fan_part_number */
+static ssize_t dfd_get_slot_part_number(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_slot_info(slot_index, DFD_DEV_INFO_TYPE_PART_NUMBER, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to wb_get_fan_hardware_version */
+static ssize_t dfd_get_slot_hardware_version(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_slot_info(slot_index, DFD_DEV_INFO_TYPE_HW_INFO, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_fan_status */
+static ssize_t dfd_get_slot_status(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_slot_status_str(slot_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_fan_led_status */
+static ssize_t dfd_get_slot_led_status(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_led_status(WB_SLOT_LED_MODULE, slot_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_fan_led_status */
+static int dfd_set_slot_led_status(unsigned int slot_index, int status)
+{
+ int ret;
+
+ ret = dfd_set_led_status(WB_SLOT_LED_MODULE, slot_index, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_slot_power_status(unsigned int slot_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_slot_power_status_str(slot_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+static int dfd_set_slot_power_status(unsigned int slot_index, int status)
+{
+ int ret;
+
+ ret = dfd_set_slot_power_status_str(slot_index, status);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_temp_alias */
+static ssize_t dfd_get_slot_temp_alias(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_SLOT, slot_index, temp_index, WB_SENSOR_ALIAS,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_temp_type */
+static ssize_t dfd_get_slot_temp_type(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_SLOT, slot_index, temp_index, WB_SENSOR_TYPE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_temp_max */
+static ssize_t dfd_get_slot_temp_max(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_SLOT, slot_index, temp_index, WB_SENSOR_MAX,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_temp_min */
+static ssize_t dfd_get_slot_temp_min(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_SLOT, slot_index, temp_index, WB_SENSOR_MIN,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_temp_value */
+static ssize_t dfd_get_slot_temp_value(unsigned int slot_index, unsigned int temp_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_temp_info(WB_MAIN_DEV_SLOT, slot_index, temp_index, WB_SENSOR_INPUT,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_vol_alias */
+static ssize_t dfd_get_slot_vol_alias(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_SLOT, slot_index, vol_index, WB_SENSOR_ALIAS,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_vol_type */
+static ssize_t dfd_get_slot_vol_type(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_SLOT, slot_index, vol_index, WB_SENSOR_TYPE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_vol_max */
+static ssize_t dfd_get_slot_vol_max(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_SLOT, slot_index, vol_index, WB_SENSOR_MAX,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_vol_min */
+static ssize_t dfd_get_slot_vol_min(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_SLOT, slot_index, vol_index, WB_SENSOR_MIN,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_vol_range */
+static ssize_t dfd_get_slot_vol_range(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_SLOT, slot_index, vol_index, WB_SENSOR_RANGE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_vol_nominal_value */
+static ssize_t dfd_get_slot_vol_nominal_value(unsigned int slot_index,
+ unsigned int vol_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_SLOT, slot_index, vol_index, WB_SENSOR_NOMINAL_VAL,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_vol_value */
+static ssize_t dfd_get_slot_vol_value(unsigned int slot_index, unsigned int vol_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_voltage_info(WB_MAIN_DEV_SLOT, slot_index, vol_index, WB_SENSOR_INPUT,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_curr_alias */
+static ssize_t dfd_get_slot_curr_alias(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_SLOT, slot_index, curr_index, WB_SENSOR_ALIAS,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_curr_type */
+static ssize_t dfd_get_slot_curr_type(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_SLOT, slot_index, curr_index, WB_SENSOR_TYPE,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_curr_max */
+static ssize_t dfd_get_slot_curr_max(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_SLOT, slot_index, curr_index, WB_SENSOR_MAX,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_curr_min */
+static ssize_t dfd_get_slot_curr_min(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_SLOT, slot_index, curr_index, WB_SENSOR_MIN,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_curr_value */
+static ssize_t dfd_get_slot_curr_value(unsigned int slot_index, unsigned int curr_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_current_info(WB_MAIN_DEV_SLOT, slot_index, curr_index, WB_SENSOR_INPUT,
+ buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_fpga_alias */
+static ssize_t dfd_get_slot_fpga_alias(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_name(slot_index, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_fpga_type */
+static ssize_t dfd_get_slot_fpga_type(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_type(slot_index, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_fpga_firmware_version */
+static ssize_t dfd_get_slot_fpga_firmware_version(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_fw_version(slot_index, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_fpga_board_version */
+static ssize_t dfd_get_slot_fpga_board_version(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_hw_version(slot_index, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_fpga_test_reg */
+static ssize_t dfd_get_slot_fpga_test_reg(unsigned int slot_index, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_fpga_testreg_str(slot_index, fpga_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_main_board_fpga_test_reg */
+static int dfd_set_slot_fpga_test_reg(unsigned int slot_index, unsigned int fpga_index,
+ unsigned int value)
+{
+ int ret;
+
+ ret = dfd_set_fpga_testreg(slot_index, fpga_index - 1, value);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_cpld_alias */
+static ssize_t dfd_get_slot_cpld_alias(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_name(slot_index, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_cpld_type */
+static ssize_t dfd_get_slot_cpld_type(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_type(slot_index, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_cpld_firmware_version */
+static ssize_t dfd_get_slot_cpld_firmware_version(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_fw_version(slot_index, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_cpld_board_version */
+static ssize_t dfd_get_slot_cpld_board_version(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_hw_version(slot_index, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_get_main_board_cpld_test_reg */
+static ssize_t dfd_get_slot_cpld_test_reg(unsigned int slot_index, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_cpld_testreg_str(slot_index, cpld_index - 1, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/* Similar to dfd_set_main_board_cpld_test_reg */
+static int dfd_set_slot_cpld_test_reg(unsigned int slot_index, unsigned int cpld_index,
+ unsigned int value)
+{
+ int ret;
+
+ ret = dfd_set_cpld_testreg(slot_index, cpld_index - 1, value);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+/***************************************end of slot*******************************************/
+/*****************************************system*********************************************/
+static ssize_t dfd_get_system_value(unsigned int type, int *value, char *buf, size_t count)
+{
+ int ret;
+
+ ret = dfd_system_get_system_value(type, value);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", *value);
+}
+
+static ssize_t dfd_set_system_value(unsigned int type, int value)
+{
+ int ret;
+
+ ret = dfd_system_set_system_value(type, value);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+static ssize_t dfd_get_system_port_power_status(unsigned int type, char *buf, size_t count)
+{
+ int ret;
+
+ ret = dfd_system_get_port_power_status(type, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+/*************************************end of system*****************************************/
+/*****************************************eeprom*********************************************/
+static int dfd_get_eeprom_number(void)
+{
+ int ret;
+
+ ret = dfd_get_dev_number(WB_MAIN_DEV_MAINBOARD, WB_MINOR_DEV_EEPROM);
+ return ret;
+}
+
+/*
+ * dfd_get_board_eeprom_size - Used to get board eeprom size, including slots eeprom
+ *
+ * This function returns the size of board eeprom, including slots eeprom
+ * otherwise it returns a negative value on failed.
+ */
+static int dfd_get_board_eeprom_size(unsigned int e2_index)
+{
+ int ret;
+
+ ret = dfd_get_eeprom_size(WB_MAIN_DEV_MAINBOARD, e2_index);
+ return ret;
+}
+
+/*
+ * dfd_get_board_eeprom_alias - Used to get board eeprom alias, including slots eeprom
+ *
+ * This function returns the alias of board eeprom, including slots eeprom
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_board_eeprom_alias(unsigned int e2_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_eeprom_alias(WB_MAIN_DEV_MAINBOARD, e2_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_board_eeprom_tag - Used to get board eeprom tag, including slots eeprom
+ *
+ * This function returns the alias of board eeprom, including slots eeprom
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_board_eeprom_tag(unsigned int e2_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_eeprom_tag(WB_MAIN_DEV_MAINBOARD, e2_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_get_board_eeprom_type - Used to get board eeprom type, including slots eeprom
+ *
+ * This function returns the type of board eeprom, including slots eeprom
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_get_board_eeprom_type(unsigned int e2_index, char *buf, size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_get_eeprom_type(WB_MAIN_DEV_MAINBOARD, e2_index, buf, count);
+ if (ret < 0) {
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, count, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+ return ret;
+}
+
+/*
+ * dfd_read_board_eeprom_data - Used to read board eeprom data, including slots eeprom
+ * @buf: Data read buffer
+ * @offset: offset address to read board eeprom data, including slots eeprom
+ * @count: length of buf
+ *
+ * This function returns the length of the filled buffer,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_read_board_eeprom_data(unsigned int e2_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_read_eeprom_data(WB_MAIN_DEV_MAINBOARD, e2_index, buf, offset, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*
+ * dfd_write_board_eeprom_data - Used to write board eeprom data, including slots eeprom
+ * @buf: Data write buffer
+ * @offset: offset address to write board eeprom data, including slots eeprom
+ * @count: length of buf
+ *
+ * This function returns the written length of eeprom,
+ * returns 0 means EOF,
+ * otherwise it returns a negative value on failed.
+ */
+static ssize_t dfd_write_board_eeprom_data(unsigned int e2_index, char *buf, loff_t offset,
+ size_t count)
+{
+ ssize_t ret;
+
+ ret = dfd_write_eeprom_data(WB_MAIN_DEV_MAINBOARD, e2_index, buf, offset, count);
+ if (ret == -DFD_RV_DEV_NOTSUPPORT) {
+ return -WB_SYSFS_RV_UNSUPPORT;
+ }
+ return ret;
+}
+
+/*************************************end of eeprom*****************************************/
+
+
+static struct switch_drivers_s switch_drivers = {
+ /*
+ * set odm switch drivers,
+ * if not support the function, set corresponding hook to NULL.
+ */
+ /* temperature sensors */
+ .get_main_board_temp_number = dfd_get_main_board_temp_number,
+ .get_main_board_temp_alias = dfd_get_main_board_temp_alias,
+ .get_main_board_temp_type = dfd_get_main_board_temp_type,
+ .get_main_board_temp_max = dfd_get_main_board_temp_max,
+ .get_main_board_temp_min = dfd_get_main_board_temp_min,
+ .get_main_board_temp_value = dfd_get_main_board_temp_value,
+ .get_main_board_temp_high = dfd_get_main_board_temp_high,
+ .get_main_board_temp_low = dfd_get_main_board_temp_low,
+ .get_main_board_temp_monitor_flag = dfd_get_main_board_temp_monitor_flag,
+ /* voltage sensors */
+ .get_main_board_vol_number = dfd_get_main_board_vol_number,
+ .get_main_board_vol_alias = dfd_get_main_board_vol_alias,
+ .get_main_board_vol_type = dfd_get_main_board_vol_type,
+ .get_main_board_vol_max = dfd_get_main_board_vol_max,
+ .get_main_board_vol_min = dfd_get_main_board_vol_min,
+ .get_main_board_vol_range = dfd_get_main_board_vol_range,
+ .get_main_board_vol_nominal_value = dfd_get_main_board_vol_nominal_value,
+ .get_main_board_vol_value = dfd_get_main_board_vol_value,
+ .get_main_board_vol_monitor_flag = dfd_get_main_board_vol_monitor_flag,
+ /* current sensors */
+ .get_main_board_curr_number = dfd_get_main_board_curr_number,
+ .get_main_board_curr_alias = dfd_get_main_board_curr_alias,
+ .get_main_board_curr_type = dfd_get_main_board_curr_type,
+ .get_main_board_curr_max = dfd_get_main_board_curr_max,
+ .get_main_board_curr_min = dfd_get_main_board_curr_min,
+ .get_main_board_curr_value = dfd_get_main_board_curr_value,
+ .get_main_board_curr_monitor_flag = dfd_get_main_board_curr_monitor_flag,
+ /* syseeprom */
+ .get_syseeprom_size = dfd_get_syseeprom_size,
+ .read_syseeprom_data = dfd_read_syseeprom_data,
+ .write_syseeprom_data = dfd_write_syseeprom_data,
+ /* fan */
+ .get_fan_number = dfd_get_fan_number,
+ .get_fan_motor_number = dfd_get_fan_motor_number,
+ .get_fan_model_name = dfd_get_fan_model_name,
+ .get_fan_vendor = dfd_get_fan_vendor,
+ .get_fan_serial_number = dfd_get_fan_serial_number,
+ .get_fan_part_number = dfd_get_fan_part_number,
+ .get_fan_hardware_version = dfd_get_fan_hardware_version,
+ .get_fan_status = dfd_get_fan_status,
+ .get_fan_present = dfd_get_fan_present,
+ .get_fan_led_status = dfd_get_fan_led_status,
+ .set_fan_led_status = dfd_set_fan_led_status,
+ .get_fan_direction = dfd_get_fan_direction,
+ .get_fan_motor_status = dfd_get_fan_motor_status,
+ .get_fan_motor_speed = dfd_get_fan_motor_speed,
+ .get_fan_motor_speed_tolerance = dfd_get_fan_motor_speed_tolerance,
+ .get_fan_motor_speed_target = dfd_get_fan_motor_speed_target,
+ .get_fan_motor_speed_max = dfd_get_fan_motor_speed_max,
+ .get_fan_motor_speed_min = dfd_get_fan_motor_speed_min,
+ .get_fan_ratio = dfd_get_fan_ratio,
+ .set_fan_ratio = dfd_set_fan_ratio,
+ /* psu */
+ .get_psu_number = dfd_get_psu_number,
+ .get_psu_temp_number = dfd_get_psu_temp_number,
+ .get_psu_model_name = dfd_get_psu_model_name,
+ .get_psu_vendor = dfd_get_psu_vendor,
+ .get_psu_date = dfd_get_psu_date,
+ .get_psu_status = dfd_get_psu_status,
+ .get_psu_hw_status = dfd_get_psu_hw_status,
+ .get_psu_alarm = dfd_get_psu_alarm,
+ .get_psu_serial_number = dfd_get_psu_serial_number,
+ .get_psu_part_number = dfd_get_psu_part_number,
+ .get_psu_hardware_version = dfd_get_psu_hardware_version,
+ .get_psu_type = dfd_get_psu_type,
+ .get_psu_in_curr = dfd_get_psu_in_curr,
+ .get_psu_in_vol = dfd_get_psu_in_vol,
+ .get_psu_in_power = dfd_get_psu_in_power,
+ .get_psu_out_curr = dfd_get_psu_out_curr,
+ .get_psu_out_vol = dfd_get_psu_out_vol,
+ .get_psu_out_power = dfd_get_psu_out_power,
+ .get_psu_out_max_power = dfd_get_psu_out_max_power,
+ .get_psu_present_status = dfd_get_psu_present,
+ .get_psu_in_status = dfd_get_psu_in_status,
+ .get_psu_out_status = dfd_get_psu_out_status,
+ .get_psu_status_pmbus = dfd_get_psu_status_pmbus,
+ .get_psu_fan_speed = dfd_get_psu_fan_speed,
+ .get_psu_fan_ratio = dfd_get_psu_fan_ratio,
+ .set_psu_fan_ratio = dfd_set_psu_fan_ratio,
+ .get_psu_fan_direction = dfd_get_psu_fan_direction,
+ .get_psu_led_status = dfd_get_psu_led_status,
+ .get_psu_temp_alias = dfd_get_psu_temp_alias,
+ .get_psu_temp_type = dfd_get_psu_temp_type,
+ .get_psu_temp_max = dfd_get_psu_temp_max,
+ .set_psu_temp_max = dfd_set_psu_temp_max,
+ .get_psu_temp_min = dfd_get_psu_temp_min,
+ .set_psu_temp_min = dfd_set_psu_temp_min,
+ .get_psu_temp_value = dfd_get_psu_temp_value,
+ .get_psu_fan_speed_cal = dfd_get_psu_fan_speed_cal,
+ .get_psu_attr_threshold = dfd_get_psu_attr_threshold,
+ .get_psu_eeprom_size = dfd_get_psu_eeprom_size,
+ .read_psu_eeprom_data = dfd_read_psu_eeprom_data,
+ .get_psu_blackbox_info = dfd_get_psu_blackbox_info,
+ .get_psu_pmbus_info = dfd_get_psu_pmbus_info,
+ .clear_psu_blackbox = dfd_clear_psu_blackbox_info,
+ /* transceiver */
+ .get_eth_number = dfd_get_eth_number,
+ .get_transceiver_power_on_status = dfd_get_transceiver_power_on_status,
+ .set_transceiver_power_on_status = dfd_set_transceiver_power_on_status,
+ .get_eth_power_on_status = dfd_get_eth_power_on_status,
+ .set_eth_power_on_status = dfd_set_eth_power_on_status,
+ .get_eth_tx_fault_status = dfd_get_eth_tx_fault_status,
+ .get_eth_tx_disable_status = dfd_get_eth_tx_disable_status,
+ .set_eth_tx_disable_status = dfd_set_eth_tx_disable_status,
+ .get_transceiver_present_status = dfd_get_transceiver_present_status,
+ .get_eth_present_status = dfd_get_eth_present_status,
+ .get_eth_rx_los_status = dfd_get_eth_rx_los_status,
+ .get_eth_reset_status = dfd_get_eth_reset_status,
+ .set_eth_reset_status = dfd_set_eth_reset_status,
+ .get_eth_low_power_mode_status = dfd_get_eth_low_power_mode_status,
+ .get_eth_interrupt_status = dfd_get_eth_interrupt_status,
+ .get_eth_eeprom_size = dfd_get_eth_eeprom_size,
+ .read_eth_eeprom_data = dfd_read_eth_eeprom_data,
+ .write_eth_eeprom_data = dfd_write_eth_eeprom_data,
+ .get_eth_optoe_type = dfd_get_eth_optoe_type,
+ .set_eth_optoe_type = dfd_set_eth_optoe_type,
+ /* sysled */
+ .get_sys_led_status = dfd_get_sys_led_status,
+ .set_sys_led_status = dfd_set_sys_led_status,
+ .get_bmc_led_status = dfd_get_bmc_led_status,
+ .set_bmc_led_status = dfd_set_bmc_led_status,
+ .get_sys_fan_led_status = dfd_get_sys_fan_led_status,
+ .set_sys_fan_led_status = dfd_set_sys_fan_led_status,
+ .get_sys_psu_led_status = dfd_get_sys_psu_led_status,
+ .set_sys_psu_led_status = dfd_set_sys_psu_led_status,
+ .get_id_led_status = dfd_get_id_led_status,
+ .set_id_led_status = dfd_set_id_led_status,
+ /* FPGA */
+ .get_main_board_fpga_number = dfd_get_main_board_fpga_number,
+ .get_main_board_fpga_alias = dfd_get_main_board_fpga_alias,
+ .get_main_board_fpga_type = dfd_get_main_board_fpga_type,
+ .get_main_board_fpga_firmware_version = dfd_get_main_board_fpga_firmware_version,
+ .get_main_board_fpga_board_version = dfd_get_main_board_fpga_board_version,
+ .get_main_board_fpga_test_reg = dfd_get_main_board_fpga_test_reg,
+ .set_main_board_fpga_test_reg = dfd_set_main_board_fpga_test_reg,
+ /* CPLD */
+ .get_main_board_cpld_number = dfd_get_main_board_cpld_number,
+ .get_main_board_cpld_alias = dfd_get_main_board_cpld_alias,
+ .get_main_board_cpld_type = dfd_get_main_board_cpld_type,
+ .get_main_board_cpld_firmware_version = dfd_get_main_board_cpld_firmware_version,
+ .get_main_board_cpld_board_version = dfd_get_main_board_cpld_board_version,
+ .get_main_board_cpld_test_reg = dfd_get_main_board_cpld_test_reg,
+ .set_main_board_cpld_test_reg = dfd_set_main_board_cpld_test_reg,
+ /* watchdog */
+ .get_watchdog_identify = dfd_get_watchdog_identify,
+ .get_watchdog_timeleft = dfd_get_watchdog_timeleft,
+ .get_watchdog_timeout = dfd_get_watchdog_timeout,
+ .set_watchdog_timeout = dfd_set_watchdog_timeout,
+ .get_watchdog_enable_status = dfd_get_watchdog_enable_status,
+ .set_watchdog_enable_status = dfd_set_watchdog_enable_status,
+ .set_watchdog_reset = dfd_set_watchdog_reset,
+ /* slot */
+ .get_slot_number = dfd_get_slot_number,
+ .get_slot_temp_number = dfd_get_slot_temp_number,
+ .get_slot_vol_number = dfd_get_slot_vol_number,
+ .get_slot_curr_number = dfd_get_slot_curr_number,
+ .get_slot_cpld_number = dfd_get_slot_cpld_number,
+ .get_slot_fpga_number = dfd_get_slot_fpga_number,
+ .get_slot_model_name = dfd_get_slot_model_name,
+ .get_slot_vendor = dfd_get_slot_vendor,
+ .get_slot_serial_number = dfd_get_slot_serial_number,
+ .get_slot_part_number = dfd_get_slot_part_number,
+ .get_slot_hardware_version = dfd_get_slot_hardware_version,
+ .get_slot_status = dfd_get_slot_status,
+ .get_slot_led_status = dfd_get_slot_led_status,
+ .set_slot_led_status = dfd_set_slot_led_status,
+ .get_slot_power_status = dfd_get_slot_power_status,
+ .set_slot_power_status = dfd_set_slot_power_status,
+ .get_slot_temp_alias = dfd_get_slot_temp_alias,
+ .get_slot_temp_type = dfd_get_slot_temp_type,
+ .get_slot_temp_max = dfd_get_slot_temp_max,
+ .get_slot_temp_min = dfd_get_slot_temp_min,
+ .get_slot_temp_value = dfd_get_slot_temp_value,
+ .get_slot_vol_alias = dfd_get_slot_vol_alias,
+ .get_slot_vol_type = dfd_get_slot_vol_type,
+ .get_slot_vol_max = dfd_get_slot_vol_max,
+ .get_slot_vol_min = dfd_get_slot_vol_min,
+ .get_slot_vol_range = dfd_get_slot_vol_range,
+ .get_slot_vol_nominal_value = dfd_get_slot_vol_nominal_value,
+ .get_slot_vol_value = dfd_get_slot_vol_value,
+ .get_slot_curr_alias = dfd_get_slot_curr_alias,
+ .get_slot_curr_type = dfd_get_slot_curr_type,
+ .get_slot_curr_max = dfd_get_slot_curr_max,
+ .get_slot_curr_min = dfd_get_slot_curr_min,
+ .get_slot_curr_value = dfd_get_slot_curr_value,
+ .get_slot_fpga_alias = dfd_get_slot_fpga_alias,
+ .get_slot_fpga_type = dfd_get_slot_fpga_type,
+ .get_slot_fpga_firmware_version = dfd_get_slot_fpga_firmware_version,
+ .get_slot_fpga_board_version = dfd_get_slot_fpga_board_version,
+ .get_slot_fpga_test_reg = dfd_get_slot_fpga_test_reg,
+ .set_slot_fpga_test_reg = dfd_set_slot_fpga_test_reg,
+ .get_slot_cpld_alias = dfd_get_slot_cpld_alias,
+ .get_slot_cpld_type = dfd_get_slot_cpld_type,
+ .get_slot_cpld_firmware_version = dfd_get_slot_cpld_firmware_version,
+ .get_slot_cpld_board_version = dfd_get_slot_cpld_board_version,
+ .get_slot_cpld_test_reg = dfd_get_slot_cpld_test_reg,
+ .set_slot_cpld_test_reg = dfd_set_slot_cpld_test_reg,
+ .get_system_value = dfd_get_system_value,
+ .get_system_port_power_status = dfd_get_system_port_power_status,
+ .set_system_value = dfd_set_system_value,
+ /* eeprom */
+ .get_eeprom_number = dfd_get_eeprom_number,
+ .get_eeprom_size = dfd_get_board_eeprom_size,
+ .get_eeprom_alias = dfd_get_board_eeprom_alias,
+ .get_eeprom_tag = dfd_get_board_eeprom_tag,
+ .get_eeprom_type = dfd_get_board_eeprom_type,
+ .read_eeprom_data = dfd_read_board_eeprom_data,
+ .write_eeprom_data = dfd_write_board_eeprom_data,
+};
+
+struct switch_drivers_s * s3ip_switch_driver_get(void)
+{
+ return &switch_drivers;
+}
+
+static int32_t __init switch_driver_init(void)
+{
+ int ret;
+
+ SWITCH_DEBUG(DBG_VERBOSE, "Enter.\n");
+ ret = wb_dev_cfg_init();
+ if (ret < 0) {
+ SWITCH_DEBUG(DBG_ERROR, "wb_dev_cfg_init failed ret %d.\n", ret);
+ return ret;
+ }
+ SWITCH_DEBUG(DBG_VERBOSE, "success.\n");
+ return 0;
+}
+
+static void __exit switch_driver_exit(void)
+{
+ SWITCH_DEBUG(DBG_VERBOSE, "switch_driver_exit.\n");
+ wb_dev_cfg_exit();
+ return;
+}
+
+module_init(switch_driver_init);
+module_exit(switch_driver_exit);
+EXPORT_SYMBOL(s3ip_switch_driver_get);
+module_param(g_switch_dbg_level, int, S_IRUGO | S_IWUSR);
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_cpld_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_cpld_driver.c
new file mode 100644
index 000000000000..d5bf876041ea
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_cpld_driver.c
@@ -0,0 +1,274 @@
+/*
+ * An wb_cpld_driver driver for cpld devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg_info.h"
+
+int g_dfd_cpld_dbg_level = 0;
+module_param(g_dfd_cpld_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/**
+ * dfd_get_cpld_name - Obtain the CPLD name
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_name(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count)
+{
+ uint64_t key;
+ char *cpld_name;
+
+ if (buf == NULL) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "param error, buf is NULL. main_dev_id: %u, cpld index: %u\n",
+ main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ if (count <= 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, cpld index: %u\n",
+ count, main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_NAME, main_dev_id, cpld_index);
+ cpld_name = dfd_ko_cfg_get_item(key);
+ if (cpld_name == NULL) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "main_dev_id: %u, cpld%u name config error, key_name:%s\n",
+ main_dev_id, cpld_index, key_to_name(DFD_CFG_ITEM_CPLD_NAME));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_CPLD_DEBUG(DBG_VERBOSE, "%s\n", cpld_name);
+ snprintf(buf, count, "%s\n", cpld_name);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_cpld_type - Obtain the CPLD model
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_type(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count)
+{
+ uint64_t key;
+ char *cpld_type;
+
+ if (buf == NULL) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, cpld index: %u\n",
+ main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ if (count <= 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, cpld index: %u\n",
+ count, main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_TYPE, main_dev_id, cpld_index);
+ cpld_type = dfd_ko_cfg_get_item(key);
+ if (cpld_type == NULL) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "main_dev_id: %u, cpld%u type config error, key_name: %s\n",
+ main_dev_id, cpld_index, key_to_name(DFD_CFG_ITEM_CPLD_TYPE));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_CPLD_DEBUG(DBG_VERBOSE, "%s\n", cpld_type);
+ snprintf(buf, count, "%s\n", cpld_type);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_cpld_fw_version - Obtain the CPLD firmware version
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_fw_version(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count)
+{
+ uint64_t key;
+ uint32_t value;
+ int rv;
+
+ if (buf == NULL) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, cpld index: %u\n",
+ main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, cpld index: %u\n",
+ count, main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_VERSION, main_dev_id, cpld_index);
+ rv = dfd_info_get_int(key, &value, NULL);
+ if (rv < 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "main_dev_id: %u, cpld%u fw config error, key_name: %s, ret: %d\n",
+ main_dev_id, cpld_index, key_to_name(DFD_CFG_ITEM_CPLD_VERSION), rv);
+ return rv;
+ }
+
+ DBG_CPLD_DEBUG(DBG_VERBOSE, "main_dev_id: %u, cpld%u firmware version: %x\n",
+ main_dev_id, cpld_index, value);
+ snprintf(buf, count, "%08x\n", value);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_cpld_hw_version - Obtain the hardware version of the CPLD
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_hw_version(uint8_t main_dev_id, unsigned int cpld_index, char *buf, size_t count)
+{
+ uint64_t key;
+ uint32_t value;
+ int rv;
+
+ if (buf == NULL) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, cpld index: %u\n",
+ main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, cpld index: %u\n",
+ count, main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_HW_VERSION, main_dev_id, cpld_index);
+ rv = dfd_info_get_int(key, &value, NULL);
+ if (rv < 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "main_dev_id: %u, cpld%u fw config error, key_name: %s, ret: %d\n",
+ main_dev_id, cpld_index, key_to_name(DFD_CFG_ITEM_CPLD_HW_VERSION), rv);
+ return rv;
+ }
+ DBG_CPLD_DEBUG(DBG_VERBOSE, "main_dev_id: %u, cpld%u hardware version 0x%x\n", main_dev_id, cpld_index, value);
+ snprintf(buf, count, "%02x\n", value);
+ return strlen(buf);
+}
+
+/**
+ * dfd_set_cpld_testreg - Set the CPLD test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @cpld_index:The number of the CPLD starts from 0
+ * @value: Writes the value of the test register
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_set_cpld_testreg(uint8_t main_dev_id, unsigned int cpld_index, int value)
+{
+ uint64_t key;
+ int ret;
+
+ if (value < 0 || value > 0xff) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "main_dev_id: %u, can't set cpld%u test reg value = 0x%02x\n",
+ main_dev_id, cpld_index, value);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_TEST_REG, main_dev_id, cpld_index);
+ ret = dfd_info_set_int(key, value);
+ if (ret < 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "main_dev_id: %u, set cpld%u test reg error, key_name: %s, ret:%d\n",
+ main_dev_id, cpld_index, key_to_name(DFD_CFG_ITEM_CPLD_TEST_REG), ret);
+ return ret;
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_cpld_testreg - Read the CPLD test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @cpld_index: The number of the CPLD starts from 0
+ * @value: Read the test register value
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_cpld_testreg(uint8_t main_dev_id, unsigned int cpld_index, int *value)
+{
+ uint64_t key;
+ int ret;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CPLD_TEST_REG, main_dev_id, cpld_index);
+ ret = dfd_info_get_int(key, value, NULL);
+ if (ret < 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "main_dev_id: %u, get cpld%u test reg error, key_name: %s, ret: %d\n",
+ main_dev_id, cpld_index, key_to_name(DFD_CFG_ITEM_CPLD_TEST_REG), ret);
+ return ret;
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_cpld_testreg_str - Read the CPLD test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @cpld_index: The number of the CPLD starts from 0
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_cpld_testreg_str(uint8_t main_dev_id, unsigned int cpld_index,
+ char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, cpld index: %u\n",
+ main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_CPLD_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, cpld index: %u\n",
+ count, main_dev_id, cpld_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ ret = dfd_get_cpld_testreg(main_dev_id, cpld_index, &value);
+ if (ret < 0) {
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "0x%02x\n", value);
+}
+
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_eeprom_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_eeprom_driver.c
new file mode 100644
index 000000000000..7a3b760c2266
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_eeprom_driver.c
@@ -0,0 +1,230 @@
+/*
+ * An wb_eeprom_driver driver for eeprom devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_tlveeprom.h"
+
+int g_dfd_eeprom_dbg_level = 0;
+module_param(g_dfd_eeprom_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/**
+ * dfd_get_eeprom_size - Gets the data size of the eeprom
+ * @e2_type: This section describes the E2 type, including system, PSU, fan, and module E2
+ * @index: E2 number
+ * return: Succeeded: The data size of the eeprom is returned
+ * : Failed: A negative value is returned
+ */
+int dfd_get_eeprom_size(int e2_type, int index)
+{
+ uint64_t key;
+ int *p_eeprom_size;
+
+ /* Obtain the eeprom size */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_EEPROM_SIZE, e2_type, index);
+
+ p_eeprom_size = dfd_ko_cfg_get_item(key);
+ if (p_eeprom_size == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "get eeprom size error. key_name:%s\n",
+ key_to_name(DFD_CFG_ITEM_EEPROM_SIZE));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ return *p_eeprom_size;
+}
+
+/**
+ * dfd_read_eeprom_data - Read eeprom data
+ * @e2_type: This section describes the E2 type, including system, PSU, fan, and module E2
+ * @index: E2 number
+ * @buf: eeprom data receives buf
+ * @offset: The offset address of the read
+ * @count: Read length
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_read_eeprom_data(int e2_type, int index, char *buf, loff_t offset, size_t count)
+{
+ uint64_t key;
+ ssize_t rd_len;
+ char *eeprom_path;
+
+ if (buf == NULL || offset < 0 || count <= 0) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "params error, offset: 0x%llx, rd_count: %lu.\n",
+ offset, count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Obtain the eeprom read path*/
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_EEPROM_PATH, e2_type, index);
+ eeprom_path = dfd_ko_cfg_get_item(key);
+ if (eeprom_path == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "get eeprom path error, e2_type: %d, index: %d, key_name: %s\n",
+ e2_type, index, key_to_name(DFD_CFG_ITEM_EEPROM_PATH));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_EEPROM_DEBUG(DBG_VERBOSE, "e2_type: %d, index: %d, path: %s, offset: 0x%llx, \
+ rd_count: %lu\n", e2_type, index, eeprom_path, offset, count);
+
+ mem_clear(buf, count);
+ rd_len = dfd_ko_read_file(eeprom_path, offset, buf, count);
+ if (rd_len < 0) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "read eeprom data failed, loc: %s, offset: 0x%llx, \
+ rd_count: %lu, ret: %ld,\n", eeprom_path, offset, count, rd_len);
+ } else {
+ DBG_EEPROM_DEBUG(DBG_VERBOSE, "read eeprom data success, loc: %s, offset: 0x%llx, \
+ rd_count: %lu, rd_len: %ld,\n", eeprom_path, offset, count, rd_len);
+ }
+
+ return rd_len;
+}
+
+/**
+ * dfd_write_eeprom_data - Write eeprom data
+ * @e2_type: This section describes the E2 type, including system, PSU, fan, and module E2
+ * @index: E2 number
+ * @buf: eeprom data buf
+ * @offset: The offset address of the write
+ * @count: Write length
+ * return: Success: The length of the written data is returned
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_write_eeprom_data(int e2_type, int index, char *buf, loff_t offset, size_t count)
+{
+ uint64_t key;
+ ssize_t wr_len;
+ char *eeprom_path;
+
+ if (buf == NULL || offset < 0 || count <= 0) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "params error, offset: 0x%llx, count: %lu.\n", offset, count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Obtain the eeprom read path */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_EEPROM_PATH, e2_type, index);
+ eeprom_path = dfd_ko_cfg_get_item(key);
+ if (eeprom_path == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "get eeprom path error, e2_type: %d, index: %d, key_name: %s\n",
+ e2_type, index, key_to_name(DFD_CFG_ITEM_EEPROM_PATH));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_EEPROM_DEBUG(DBG_VERBOSE, "e2_type: %d, index: %d, path: %s, offset: 0x%llx, \
+ wr_count: %lu.\n", e2_type, index, eeprom_path, offset, count);
+
+ wr_len = dfd_ko_write_file(eeprom_path, offset, buf, count);
+ if (wr_len < 0) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "write eeprom data failed, loc:%s, offset: 0x%llx, \
+ wr_count: %lu, ret: %ld.\n", eeprom_path, offset, count, wr_len);
+ } else {
+ DBG_EEPROM_DEBUG(DBG_VERBOSE, "write eeprom data success, loc:%s, offset: 0x%llx, \
+ wr_count: %lu, wr_len: %ld.\n", eeprom_path, offset, count, wr_len);
+ }
+
+ return wr_len;
+}
+
+ssize_t dfd_get_eeprom_alias(int e2_type, unsigned int e2_index, char *buf, size_t count)
+{
+ uint64_t key;
+ char *e2_alias;
+
+ if (buf == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "param error buf is NULL.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "buf size error, count: %lu\n", count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_EEPROM_ALIAS, e2_type, e2_index);
+ e2_alias = dfd_ko_cfg_get_item(key);
+ if (e2_alias == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "get eeprom alias config error, e2_type: %d, e2_index: %u, key_name: %s\n",
+ e2_type, e2_index, key_to_name(DFD_CFG_ITEM_EEPROM_ALIAS));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "%s\n", e2_alias);
+ snprintf(buf, count, "%s\n", e2_alias);
+ return strlen(buf);
+}
+
+ssize_t dfd_get_eeprom_tag(int e2_type, unsigned int e2_index, char *buf, size_t count)
+{
+ uint64_t key;
+ char *e2_tag;
+
+ if (buf == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "param error buf is NULL.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "buf size error, count: %lu\n", count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_EEPROM_TAG, e2_type, e2_index);
+ e2_tag = dfd_ko_cfg_get_item(key);
+ if (e2_tag == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "get eeprom tag config error, e2_type: %d, e2_index: %u, key: %s\n",
+ e2_type, e2_index, key_to_name(DFD_CFG_ITEM_EEPROM_TAG));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "%s\n", e2_tag);
+ snprintf(buf, count, "%s\n", e2_tag);
+ return strlen(buf);
+}
+
+ssize_t dfd_get_eeprom_type(int e2_type, unsigned int e2_index, char *buf, size_t count)
+{
+ uint64_t key;
+ char *eeprom_type;
+
+ if (buf == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "param error buf is NULL.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "buf size error, count: %lu\n", count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_EEPROM_TYPE, e2_type, e2_index);
+ eeprom_type = dfd_ko_cfg_get_item(key);
+ if (eeprom_type == NULL) {
+ DBG_EEPROM_DEBUG(DBG_ERROR, "get eeprom type config error, e2_type: %d, e2_index: %u, key_name: %s\n",
+ e2_type, e2_index, key_to_name(DFD_CFG_ITEM_EEPROM_TYPE));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "%s\n", eeprom_type);
+ snprintf(buf, count, "%s\n", eeprom_type);
+ return strlen(buf);
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_fan_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_fan_driver.c
new file mode 100644
index 000000000000..77f88429edfb
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_fan_driver.c
@@ -0,0 +1,1093 @@
+/*
+ * An wb_fan_driver driver for fan devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg_info.h"
+#include "dfd_frueeprom.h"
+
+#define DFD_FAN_EEPROM_MODE_TLV_STRING "tlv"
+#define DFD_FAN_EEPROM_MODE_FRU_STRING "fru"
+#define FAN_SIZE (256)
+
+typedef enum fan_present_status_e {
+ ABSENT = 0,
+ PRESENT = 1,
+} fan_present_status_t;
+
+typedef enum fan_motor_status_e {
+ MOTOR_STALL = 0,
+ MOTOR_ROLL = 1,
+} fan_motor_status_t;
+
+typedef enum fan_eeprom_mode_e {
+ FAN_EEPROM_MODE_TLV, /* TLV */
+ FAN_EEPROM_MODE_FRU, /*FRU*/
+} fan_eeprom_mode_t;
+
+typedef struct dfd_dev_head_info_s {
+ uint8_t ver; /* The version number defined in the E2PROM file, initially 0x01 */
+ uint8_t flag; /* The new version E2PROM is identified as 0x7E */
+ uint8_t hw_ver; /* It consists of two parts: the main version number and the revised version */
+ uint8_t type; /* Hardware type definition information */
+ int16_t tlv_len; /* Valid data length (16 bits) */
+} dfd_dev_head_info_t;
+
+typedef struct dfd_dev_tlv_info_s {
+ uint8_t type; /* Data type */
+ uint8_t len; /* Data length */
+ uint8_t data[0]; /* Data */
+} dfd_dev_tlv_info_t;
+
+/* Specifies the fixed value of the fan speed */
+typedef enum wb_fan_threshold_e {
+ FAN_SPEED_MIN = 1, /* Minimum value */
+ FAN_SPEED_MAX = 2, /* Maximum value */
+ FAN_SPEED_TOLERANCE = 3, /* tolerance */
+ FAN_SPEED_TARGET_0 = 0x10, /* index of the rated speed when PWM=0x */
+ FAN_SPEED_TARGET_10 = 0x11,
+ FAN_SPEED_TARGET_20 = 0x12,
+ FAN_SPEED_TARGET_30 = 0x13,
+ FAN_SPEED_TARGET_40 = 0x14,
+ FAN_SPEED_TARGET_50 = 0x15,
+ FAN_SPEED_TARGET_60 = 0x16,
+ FAN_SPEED_TARGET_70 = 0x17,
+ FAN_SPEED_TARGET_80 = 0x18,
+ FAN_SPEED_TARGET_90 = 0x19,
+ FAN_SPEED_TARGET_100 = 0x1a, /* index of the rated speed when PWM=100 */
+
+} wb_fan_threshold_t;
+
+/* fan_threshold_[Threshold type(high 8bit)+Master device type(low 8bit)]_[subdevice ID(high 4bit)+Front and rear motor id(low 4bit)] */
+#define DFD_GET_FAN_THRESHOLD_KEY1(threshold_type, main_dev_id) \
+ (((threshold_type & 0xff) << 8) | (main_dev_id & 0xff))
+#define DFD_GET_FAN_THRESHOLD_KEY2(sub_type_id, motor_id) \
+ (((sub_type_id & 0x0f) << 4) | (motor_id & 0x0f))
+
+int g_dfd_fan_dbg_level = 0;
+module_param(g_dfd_fan_dbg_level, int, S_IRUGO | S_IWUSR);
+
+static char *dfd_get_fan_sysfs_name(void)
+{
+ uint64_t key;
+ char *sysfs_name;
+
+ /* string type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_SYSFS_NAME, 0, 0);
+ sysfs_name = dfd_ko_cfg_get_item(key);
+ if (sysfs_name == NULL) {
+ DFD_FAN_DEBUG(DBG_VERBOSE, "key_name=%s, sysfs_name is NULL, use default way.\n",
+ key_to_name(DFD_CFG_ITEM_FAN_SYSFS_NAME));
+ } else {
+ DFD_FAN_DEBUG(DBG_VERBOSE, "sysfs_name: %s.\n", sysfs_name);
+ }
+ return sysfs_name;
+}
+
+/**
+ * dfd_get_fan_eeprom_mode - The fan type E2 is obtained
+ * return: 0:TLV
+ * 1:FRU
+ * : Negative value - Read failed
+ */
+static int dfd_get_fan_eeprom_mode(void)
+{
+ uint64_t key;
+ int mode;
+ char *name;
+
+ /* string type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_E2_MODE, 0, 0);
+ name = dfd_ko_cfg_get_item(key);
+ if (name == NULL) {
+ /* By default, the TLV format is returned */
+ DFD_FAN_DEBUG(DBG_WARN, "get fan eeprom mode fail, key_name=%s\n",
+ key_to_name(DFD_CFG_ITEM_FAN_E2_MODE));
+ return FAN_EEPROM_MODE_TLV;
+ }
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "fan eeprom mode_name %s.\n", name);
+ if (!strncmp(name, DFD_FAN_EEPROM_MODE_TLV_STRING, strlen(DFD_FAN_EEPROM_MODE_TLV_STRING))) {
+ mode = FAN_EEPROM_MODE_TLV;
+ } else if (!strncmp(name, DFD_FAN_EEPROM_MODE_FRU_STRING, strlen(DFD_FAN_EEPROM_MODE_FRU_STRING))) {
+ mode = FAN_EEPROM_MODE_FRU;
+ } else {
+ /* The default TLV mode is returned */
+ mode = FAN_EEPROM_MODE_TLV;
+ }
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "fan eeprom mode %d.\n", mode);
+ return mode;
+}
+
+static int dfd_fan_tlv_eeprom_read(int bus, int addr, uint8_t cmd, char *buf, int len,
+ const char *sysfs_name)
+{
+ dfd_dev_head_info_t info;
+ char tmp_tlv_len[sizeof(uint16_t)];
+ char *tlv_data;
+ dfd_dev_tlv_info_t *tlv;
+ int buf_len;
+ int rv, match_flag;
+
+ rv = dfd_ko_i2c_read(bus, addr, 0, (uint8_t *)&info, sizeof(dfd_dev_head_info_t), sysfs_name);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "read fan i2c failed, bus: %d, addr: 0x%x, rv: %d\n",
+ bus, addr, rv);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ /* convert TLV_LEN */
+ memcpy(tmp_tlv_len, (uint8_t *)&info.tlv_len, sizeof(uint16_t));
+ info.tlv_len = (tmp_tlv_len[0] << 8) + tmp_tlv_len[1];
+
+ if ((info.tlv_len <= 0) || (info.tlv_len > 0xFF)) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan maybe not set mac.\n");
+ return -DFD_RV_TYPE_ERR;
+ }
+ DFD_FAN_DEBUG(DBG_VERBOSE, "info.tlv_len: %d\n", info.tlv_len);
+
+ tlv_data = (uint8_t *)kmalloc(info.tlv_len, GFP_KERNEL);
+ if (tlv_data == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "tlv_data kmalloc failed \n");
+ return -DFD_RV_NO_MEMORY;
+ }
+ mem_clear(tlv_data, info.tlv_len);
+
+ rv = dfd_ko_i2c_read(bus, addr, sizeof(dfd_dev_head_info_t), tlv_data, info.tlv_len, sysfs_name);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR,"fan eeprom read failed\n");
+ kfree(tlv_data);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ buf_len = len - 1;
+ match_flag = 0;
+ for (tlv = (dfd_dev_tlv_info_t *)tlv_data; (ulong)tlv < (ulong)tlv_data + info.tlv_len;) {
+ DFD_FAN_DEBUG(DBG_VERBOSE, "tlv: %p, tlv->type: 0x%x, tlv->len: 0x%x info->tlv_len: 0x%x\n",
+ tlv, tlv->type, tlv->len, info.tlv_len);
+ if (tlv->type == cmd && tlv->len <= buf_len) {
+ DFD_FAN_DEBUG(DBG_VERBOSE, "find tlv data, copy...\n");
+ memcpy(buf, (uint8_t *)tlv->data, tlv->len);
+ buf_len = (uint32_t)tlv->len;
+ match_flag = 1;
+ break;
+ }
+ tlv = (dfd_dev_tlv_info_t *)((uint8_t*)tlv + sizeof(dfd_dev_tlv_info_t) + tlv->len);
+ }
+ kfree(tlv_data);
+ if (match_flag == 0) {
+ DFD_FAN_DEBUG(DBG_ERROR,"can't find fan tlv date. bus: %d, addr: 0x%02x, tlv type: %d.\n",
+ bus, addr, cmd);
+ return -DFD_RV_TYPE_ERR;
+ }
+ return buf_len;
+}
+
+/**
+ * dfd_get_fan_present_status - Obtain the fan running status
+ * @index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * return: 0:STALL
+ * 1:ROLL
+ * : Negative value - Read failed
+ */
+static int dfd_get_fan_roll_status(unsigned int fan_index, unsigned int motor_index)
+{
+ uint64_t key;
+ int ret;
+ int status;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_ROLL_STATUS, fan_index, motor_index);
+ ret = dfd_info_get_int(key, &status, NULL);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan roll status error, fan: %u, motor: %u, key_name: %s\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_ROLL_STATUS));
+ return ret;
+ }
+ return status;
+}
+
+/**
+ * dfd_get_fan_present_status - Obtain the fan status
+ * @index: Number of the fan, starting from 1
+ * return: 0:ABSENT
+ * 1:PRESENT
+ * : Negative value - Read failed
+ */
+int dfd_get_fan_present_status(unsigned int fan_index)
+{
+ uint64_t key;
+ int ret;
+ int status;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_DEV_PRESENT_STATUS, WB_MAIN_DEV_FAN, fan_index);
+ ret = dfd_info_get_int(key, &status, NULL);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan present status error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_DEV_PRESENT_STATUS));
+ return ret;
+ }
+ return status;
+}
+
+/**
+ * dfd_get_fan_status - Obtaining fan status
+ * @index: Number of the fan, starting from 1
+ * return: 0:ABSENT
+ * 1:OK
+ * 2:NOT OK
+ * : Negative value - Read failed
+ */
+static int dfd_get_fan_status(unsigned int fan_index)
+{
+ int motor_num, motor_index, status, errcnt;
+
+ /* Obtaining fan status */
+ status = dfd_get_fan_present_status(fan_index);
+ if (status != PRESENT) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan index: %u, status: %d\n", fan_index, status);
+ return status;
+ }
+
+ /* Get the motor running state */
+ motor_num = dfd_get_dev_number(WB_MAIN_DEV_FAN, WB_MINOR_DEV_MOTOR);
+ if (motor_num <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get motor number error: %d\n", motor_num);
+ return -DFD_RV_DEV_FAIL;
+ }
+ errcnt = 0;
+ for (motor_index = 1; motor_index <= motor_num; motor_index++) {
+ status = dfd_get_fan_roll_status(fan_index, motor_index);
+ if (status < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan roll status error, fan index: %u, motor index: %d, status: %d\n",
+ fan_index, motor_index, status);
+ return status;
+ }
+ if (status != MOTOR_ROLL) {
+ DFD_FAN_DEBUG(DBG_ERROR,
+ "stall:fan index: %u, motor index: %d, status: %d\n",fan_index, motor_index, status);
+ errcnt++;
+ }
+ }
+ if (errcnt > 0) {
+ return FAN_STATUS_NOT_OK;
+ }
+ return FAN_STATUS_OK;
+}
+
+/**
+ * dfd_get_fan_status_str - Obtaining fan status
+ * @index: Number of the fan, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_fan_status_str(unsigned int fan_index, char *buf, size_t count)
+{
+ int ret;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "params error, fan_index: %u count: %lu",
+ fan_index, count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u\n",
+ count, fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ ret = dfd_get_fan_status(fan_index);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan status error, ret: %d, fan_index: %u\n",
+ ret, fan_index);
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", ret);
+}
+
+
+/**
+ * dfd_get_fan_present_str - Obtaining fan present status
+ * @index: Number of the fan, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_fan_present_str(unsigned int fan_index, char *buf, size_t count)
+{
+ int ret;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "params error, fan_index: %u count: %lu",
+ fan_index, count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u\n",
+ count, fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ ret = dfd_get_fan_present_status(fan_index);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan present status error, ret: %d, fan_index: %u\n",
+ ret, fan_index);
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", ret);
+}
+
+/**
+ * dfd_get_fan_motor_status_str - Obtain the fan motor status
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_status_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ int ret;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u, motor index: %u\n",
+ count, fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ ret = dfd_get_fan_roll_status(fan_index, motor_index);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan motor status error, ret: %d, fan_index: %u, motor index: %u\n",
+ ret, fan_index, motor_index);
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", ret);
+}
+
+/**
+ * dfd_fan_product_name_decode - Fan name conversion
+ * @psu_buf: Original fan name
+ * @buf_len: fan_buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+static int dfd_fan_product_name_decode(char *fan_buf, int buf_len)
+{
+ uint64_t key;
+ int i, j;
+ char *p_fan_name, *p_decode_name;
+ int *fan_type_num;
+ int *fan_display_num;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_DEV_NUM, WB_MAIN_DEV_FAN, WB_MINOR_DEV_FAN);
+ fan_display_num = dfd_ko_cfg_get_item(key);
+ if (fan_display_num == NULL) {
+ DFD_FAN_DEBUG(DBG_VERBOSE, "get fan display name number error, key_name:%s, \
+ skip fan name decode\n", key_to_name(DFD_CFG_ITEM_DEV_NUM));
+ return DFD_RV_OK;
+ }
+
+ for (i = 1; i <= *fan_display_num; i++) {
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_TYPE_NUM, i, 0);
+ fan_type_num = dfd_ko_cfg_get_item(key);
+ if (fan_type_num == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "config error, get fan type number error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_FAN_TYPE_NUM));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ for (j = 1; j <= *fan_type_num; j++) {
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_NAME, i, j);
+ p_fan_name = dfd_ko_cfg_get_item(key);
+ if (p_fan_name == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "config error, get fan origin name error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_FAN_NAME));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ if (!strncmp(fan_buf, p_fan_name, strlen(p_fan_name))) {
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_DECODE_FAN_NAME, i, 0);
+ p_decode_name = dfd_ko_cfg_get_item(key);
+ if (p_decode_name == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "config error, get fan decode name error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_DECODE_FAN_NAME));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ mem_clear(fan_buf, buf_len);
+ strlcpy(fan_buf, p_decode_name, buf_len);
+ DFD_FAN_DEBUG(DBG_VERBOSE, "fan name match ok, display fan name: %s.\n", fan_buf);
+ return DFD_RV_OK;
+ }
+ }
+ }
+
+ DFD_FAN_DEBUG(DBG_ERROR, "fan name: %s error, can't match.\n", fan_buf);
+ return -DFD_RV_DEV_NOTSUPPORT;
+}
+
+/**
+ * dfd_get_fan_info - Obtaining Fan Information
+ * @index: Number of the fan, starting from 1
+ * @cmd: Fan information type, fan name :2, fan serial number :3, fan hardware version :5
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_info(unsigned int fan_index, uint8_t cmd, char *buf, size_t count)
+{
+ uint64_t key;
+ int rv, eeprom_mode;
+ char fan_buf[FAN_SIZE];
+ dfd_i2c_dev_t *i2c_dev;
+ const char *sysfs_name;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u, cmd: 0x%x.\n", fan_index, cmd);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u, cmd: 0x%x.\n",
+ count, fan_index, cmd);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_OTHER_I2C_DEV, WB_MAIN_DEV_FAN, fan_index);
+ i2c_dev = dfd_ko_cfg_get_item(key);
+ if (i2c_dev == NULL) {
+ DFD_FAN_DEBUG(DBG_VERBOSE, "can't find fan%u I2C dfd config, key_name: %s\n",
+ fan_index, key_to_name(DFD_CFG_ITEM_OTHER_I2C_DEV));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ sysfs_name = dfd_get_fan_sysfs_name();
+ eeprom_mode = dfd_get_fan_eeprom_mode();
+ mem_clear(fan_buf, FAN_SIZE);
+ if (eeprom_mode == FAN_EEPROM_MODE_TLV) {
+ if (cmd == DFD_DEV_INFO_TYPE_PART_NUMBER) {
+ DFD_FAN_DEBUG(DBG_VERBOSE, "fan tlv not have part_number attributes\n");
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ rv = dfd_fan_tlv_eeprom_read(i2c_dev->bus, i2c_dev->addr, cmd, fan_buf, FAN_SIZE, sysfs_name);
+ } else {
+ if (cmd == DFD_DEV_INFO_TYPE_VENDOR) {
+ rv = dfd_get_fru_board_data(i2c_dev->bus, i2c_dev->addr, cmd, fan_buf, FAN_SIZE, sysfs_name);
+ } else {
+ rv = dfd_get_fru_data(i2c_dev->bus, i2c_dev->addr, cmd, fan_buf, FAN_SIZE, sysfs_name);
+ }
+ }
+
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan eeprom read failed");
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "%s\n", fan_buf);
+ /* Fan product name conversion */
+ if (cmd == DFD_DEV_INFO_TYPE_NAME) {
+ rv = dfd_fan_product_name_decode(fan_buf, FAN_SIZE);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan name decode error. rv: %d\n", rv);
+ }
+ }
+
+ snprintf(buf, count, "%s\n", fan_buf);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_fan_speed - Obtain the fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @speed: Speed value
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_fan_speed(unsigned int fan_index, unsigned int motor_index, unsigned int *speed)
+{
+ uint64_t key;
+ int ret, speed_tmp;
+
+ if (speed == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_SPEED, fan_index, motor_index);
+ ret = dfd_info_get_int(key, &speed_tmp, NULL);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u motor%u speed error, key: %s, ret: %d\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_SPEED), ret);
+ return ret;
+ }
+
+ if (speed_tmp == 0 || speed_tmp == 0xffff) {
+ *speed = 0;
+ } else {
+ *speed = 15000000 / speed_tmp;
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_speed_str - Obtain the fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_speed_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ int ret;
+ unsigned int speed;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u, motor index: %u\n",
+ count, fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ ret = dfd_get_fan_speed(fan_index, motor_index, &speed);
+ if (ret < 0) {
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", speed);
+}
+
+/**
+ * dfd_set_fan_pwm - set the fan speed duty cycle
+ * @fan_index: Number of the fan, starting from 1
+ * @pwm: Duty cycle
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_set_fan_pwm(unsigned int fan_index, int pwm)
+{
+ uint64_t key;
+ int ret, data;
+
+ if (pwm < 0 || pwm > 100) {
+ DFD_FAN_DEBUG(DBG_ERROR, "can not set pwm = %d.\n", pwm);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ data = pwm * 255 / 100;
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_RATIO, fan_index, 0);
+ ret = dfd_info_set_int(key, data);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "set fan%u ratio error, key_name: %s,ret: %d\n",
+ fan_index, key_to_name(DFD_CFG_ITEM_FAN_RATIO), ret);
+ return ret;
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_pwm - Obtain the fan speed duty cycle
+ * @fan_index: Number of the fan, starting from 1
+ * @pwm: Duty cycle
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_fan_pwm(unsigned int fan_index, int *pwm)
+{
+ uint64_t key;
+ int ret, ratio;
+
+ if (pwm == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index: %u\n", fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_RATIO, fan_index, 0);
+ ret = dfd_info_get_int(key, &ratio, NULL);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u ratio error, key_name: %s,ret: %d\n",
+ fan_index, key_to_name(DFD_CFG_ITEM_FAN_RATIO), ret);
+ return ret;
+ }
+ if ((ratio * 100) % 255 > 0) {
+ *pwm = ratio * 100 / 255 + 1;
+ } else {
+ *pwm = ratio * 100 / 255;
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_pwm_str - Obtain the fan speed duty cycle
+ * @fan_index: Number of the fan, starting from 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_pwm_str(unsigned int fan_index, char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u\n", fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u\n", count,
+ fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ ret = dfd_get_fan_pwm(fan_index, &value);
+ if (ret < 0) {
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
+
+static int dfd_get_fan_type(unsigned int fan_index, int *fan_type, int *fan_sub_type)
+{
+ int rv;
+ char fan_buf[FAN_SIZE];
+
+ /* Get the fan name */
+ rv = dfd_get_fan_info(fan_index, DFD_DEV_INFO_TYPE_NAME, fan_buf, FAN_SIZE);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u name error, ret: %d\n", fan_index, rv);
+ return rv;
+ }
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "%s\n", fan_buf);
+ dfd_info_del_no_print_string(fan_buf);
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "dfd_fan_product_name_decode get fan name %s\n", fan_buf);
+ rv = dfd_ko_cfg_get_fan_type_by_name((char *)fan_buf, fan_type, fan_sub_type);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u type by name error, ret: %d\n", fan_index, rv);
+ return -DFD_RV_NO_NODE;
+ }
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "get fan%u type %d subtype %d by name ok\n", fan_index, *fan_type, *fan_sub_type);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_speed_target - Obtain the standard fan speed
+ * @fan_index
+ * @motor_index
+ * @value Standard speed value
+ * @returns: 0 success, negative value: failed
+ */
+int dfd_get_fan_speed_target(unsigned int fan_index, unsigned int motor_index, int *value)
+{
+ uint64_t key;
+ int *p_fan_speed_target;
+ int key1, key2, fan_type, fan_sub_type, pwm;
+ int ret;
+
+ if (value == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Get the fan type */
+ ret = dfd_get_fan_type(fan_index, &fan_type, &fan_sub_type);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan get type error, rv: %d\n", ret);
+ return -EIO;
+ }
+
+ /* Get current PWM */
+ ret = dfd_get_fan_pwm(fan_index, &pwm);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Gets the rated speed corresponding to the current PWM */
+ key1 = DFD_GET_FAN_THRESHOLD_KEY1((pwm / 10 + FAN_SPEED_TARGET_0), WB_MAIN_DEV_FAN);
+ key2 = DFD_GET_FAN_THRESHOLD_KEY2(fan_type, motor_index);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_THRESHOLD, key1, key2);
+ p_fan_speed_target = dfd_ko_cfg_get_item(key);
+ if (p_fan_speed_target == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u motor%u speed target failed, key_name: %s\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ *value = *p_fan_speed_target;
+ DFD_FAN_DEBUG(DBG_VERBOSE, "get fan%u motor%u speed target ok, key_name: %s, value: %d\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD), *value);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_motor_speed_target_str - Obtain the standard fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_target_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u, motor index: %u\n",
+ count, fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ ret = dfd_get_fan_speed_target(fan_index, motor_index, &value);
+ if (ret < 0) {
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
+
+/**
+ * dfd_get_fan_motor_speed_tolerance - Obtain the fan speed tolerance
+ * @fan_index
+ * @motor_index
+ * @value Speed tolerance
+ */
+static int dfd_get_fan_motor_speed_tolerance(unsigned int fan_index, unsigned int motor_index, int *value)
+{
+ uint64_t key;
+ int *p_fan_speed_tolerance;
+ int target, ret;
+ int key1, key2, fan_type, fan_sub_type;
+
+ if (value == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index: %u, motor index: %u.\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Get the fan type */
+ ret = dfd_get_fan_type(fan_index, &fan_type, &fan_sub_type);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan get type error, ret: %d\n", ret);
+ return -EIO;
+ }
+
+ /* Obtain the error rate of the fan */
+ key1 = DFD_GET_FAN_THRESHOLD_KEY1(FAN_SPEED_TOLERANCE, WB_MAIN_DEV_FAN);
+ key2 = DFD_GET_FAN_THRESHOLD_KEY2(fan_type, motor_index);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_THRESHOLD, key1, key2);
+ p_fan_speed_tolerance = dfd_ko_cfg_get_item(key);
+ if (p_fan_speed_tolerance == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u motor%u speed tolerance failed, key_name: %s\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ /* Obtain the fan speed target */
+ ret = dfd_get_fan_speed_target(fan_index, motor_index, &target);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* error rpm = Rated speed corresponding to the current pwm * Fan error ratio / 100 */
+ *value = target * *p_fan_speed_tolerance / 100;
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "get fan%u motor%u speed tolerance ok, key: %s, tolerance rate: %d, value: %d\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD), *p_fan_speed_tolerance, *value);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_motor_speed_tolerance_str - Obtain the fan speed tolerance
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Duct type receives buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_tolerance_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u, motor index: %u\n",
+ count, fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ ret = dfd_get_fan_motor_speed_tolerance(fan_index, motor_index, &value);
+ if (ret < 0) {
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
+
+/**
+ * dfd_get_fan_direction - Obtain the fan air duct type
+ * @fan_index: The fan offset starts from 1
+ * @value 0:F2B, 1:B2F
+ * @returns: 0 success, negative value: failed
+ */
+static int dfd_get_fan_direction(unsigned int fan_index, int *value)
+{
+ uint64_t key;
+ int *p_fan_dirction;
+ int fan_type, fan_sub_type;
+ int rv;
+
+ if (value == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error, fan index: %u\n", fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Get the fan type */
+ rv = dfd_get_fan_type(fan_index, &fan_type, &fan_sub_type);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan get type error, rv: %d\n", rv);
+ return -EIO;
+ }
+
+ /* Obtain the fan direction based on the fan type and subtype */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_DIRECTION, fan_type, fan_sub_type);
+ p_fan_dirction = dfd_ko_cfg_get_item(key);
+ if (p_fan_dirction == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u direction failed, key_name: %s\n",
+ fan_index, key_to_name(DFD_CFG_ITEM_FAN_DIRECTION));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ *value = *p_fan_dirction;
+ DFD_FAN_DEBUG(DBG_VERBOSE, "get fan%u direction success, key_name: %s, value: %d\n",
+ fan_index, key_to_name(DFD_CFG_ITEM_FAN_DIRECTION), *value);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_direction_str - Obtain the fan air duct type
+ * @fan_index:The fan offset starts from 1
+ * @buf :Duct type receives buf
+ * @count :Duct type receives buf length
+ * @returns: Succeeded: Air duct type String length
+ * Failure: negative value
+ */
+ssize_t dfd_get_fan_direction_str(unsigned int fan_index, char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error, buf is NULL, fan index: %u.\n", fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error, buf is NULL, fan index: %u.\n", fan_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ ret = dfd_get_fan_direction(fan_index, &value);
+ if (ret < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan direction string failed, ret: %d, fan_index: %u\n",
+ ret, fan_index);
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
+
+/**
+ * dfd_get_fan_motor_speed_max - Obtain the maximum fan speed
+ * @fan_index
+ * @motor_index
+ * @value Maximum fan speed
+ * @returns: 0 success, negative value: failed
+ */
+static int dfd_get_fan_motor_speed_max(unsigned int fan_index, unsigned int motor_index, int *value)
+{
+ uint64_t key;
+ int *p_fan_speed_max;
+ int key1, key2, fan_type, fan_sub_type;
+ int rv;
+
+ if (value == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error, fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Get the fan type */
+ rv = dfd_get_fan_type(fan_index, &fan_type, &fan_sub_type);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan get type error, rv: %d\n", rv);
+ return -EIO;
+ }
+
+ key1 = DFD_GET_FAN_THRESHOLD_KEY1(FAN_SPEED_MAX, WB_MAIN_DEV_FAN);
+ key2 = DFD_GET_FAN_THRESHOLD_KEY2(fan_type, motor_index);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_THRESHOLD, key1, key2);
+ p_fan_speed_max = dfd_ko_cfg_get_item(key);
+ if (p_fan_speed_max == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u motor%u speed max failed, key_name: %s\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ *value = *p_fan_speed_max;
+ DFD_FAN_DEBUG(DBG_VERBOSE, "get fan%u motor%u speed max success, key_name: %s, value: %d\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD), *value);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_motor_speed_max_str - Obtain the standard fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_max_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u, motor index: %u\n",
+ count, fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ ret = dfd_get_fan_motor_speed_max(fan_index, motor_index, &value);
+ if (ret < 0) {
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
+
+/**
+ * dfd_get_fan_motor_speed_min - Obtain the minimum fan speed
+ * @fan_index
+ * @motor_index
+ * @value Minimum fan speed
+ * @returns: 0 success, negative value: failed
+ */
+static int dfd_get_fan_motor_speed_min(unsigned int fan_index, unsigned int motor_index, int *value)
+{
+ uint64_t key;
+ int *p_fan_speed_min;
+ int key1, key2, fan_type, fan_sub_type;
+ int rv;
+
+ if (value == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "param error. fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ /* Get the fan type */
+ rv = dfd_get_fan_type(fan_index, &fan_type, &fan_sub_type);
+ if (rv < 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "fan get type error, rv: %d\n", rv);
+ return -EIO;
+ }
+
+ key1 = DFD_GET_FAN_THRESHOLD_KEY1(FAN_SPEED_MIN, WB_MAIN_DEV_FAN);
+ key2 = DFD_GET_FAN_THRESHOLD_KEY2(fan_type, motor_index);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_THRESHOLD, key1, key2);
+ p_fan_speed_min = dfd_ko_cfg_get_item(key);
+ if (p_fan_speed_min == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "get fan%u motor%u speed min failed, key_name: %s\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ *value = *p_fan_speed_min;
+ DFD_FAN_DEBUG(DBG_VERBOSE, "get fan%u motor%u speed min success, key_name: %s, value: %d\n",
+ fan_index, motor_index, key_to_name(DFD_CFG_ITEM_FAN_THRESHOLD), *value);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fan_motor_speed_min_str - Obtain the standard fan speed
+ * @fan_index: Number of the fan, starting from 1
+ * @motor_index: Motor number, starting with 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fan_motor_speed_min_str(unsigned int fan_index, unsigned int motor_index,
+ char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf is NULL, fan index: %u, motor index: %u\n",
+ fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_FAN_DEBUG(DBG_ERROR, "buf size error, count: %lu, fan index: %u, motor index: %u\n",
+ count, fan_index, motor_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ ret = dfd_get_fan_motor_speed_min(fan_index, motor_index, &value);
+ if (ret < 0) {
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_fpga_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_fpga_driver.c
new file mode 100644
index 000000000000..e5c326df0eb0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_fpga_driver.c
@@ -0,0 +1,341 @@
+/*
+ * An wb_fpga_driver driver for fpga devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg_info.h"
+
+#define FPGA_REG_WIDTH_MAX (4)
+
+int g_dfd_fpga_dbg_level = 0;
+module_param(g_dfd_fpga_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/**
+ * dfd_get_fpga_name - Get the FPGA name
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:FPGA number, starting from 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_name(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count)
+{
+ uint64_t key;
+ char *fpga_name;
+
+ if (buf == NULL) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "param error, buf is NULL. main_dev_id: %u, fpga index: %u\n",
+ main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ if (count <= 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, fpga index: %u\n",
+ count, main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FPGA_NAME, main_dev_id, fpga_index);
+ fpga_name = dfd_ko_cfg_get_item(key);
+ if (fpga_name == NULL) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "main_dev_id: %u, fpga%u name config error, key_name: %s\n",
+ main_dev_id, fpga_index, key_to_name(DFD_CFG_ITEM_FPGA_NAME));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "%s\n", fpga_name);
+ snprintf(buf, count, "%s\n", fpga_name);
+ return strlen(buf);
+}
+
+static ssize_t dfd_get_fpga_model(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret, fpga_model_val;
+ char *fpga_type;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FPGA_MODEL_REG, main_dev_id, fpga_index);
+ ret = dfd_info_get_int(key, &fpga_model_val, NULL);
+ if (ret < 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "get main_dev_id: %u, fpga%u model failed, key_name: %s, ret: %d\n",
+ main_dev_id, fpga_index, key_to_name(DFD_CFG_ITEM_FPGA_MODEL_REG), ret);
+ return ret;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FPGA_MODEL_DECODE, fpga_model_val, 0);
+ fpga_type = dfd_ko_cfg_get_item(key);
+ if (fpga_type == NULL) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "main_dev_id: %u, fpga%u decode fpga model val 0x%08x failed\n",
+ main_dev_id, fpga_index, fpga_model_val);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE,
+ "main_dev_id: %u, fpga%u decode fpga model success, origin value: 0x%08x decode value: %s\n",
+ main_dev_id, fpga_index, fpga_model_val, fpga_type);
+ snprintf(buf, count, "%s\n", fpga_type);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_fpga_type - Get FPGA model
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:FPGA number, starting from 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_type(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count)
+{
+ uint64_t key;
+ char *fpga_type;
+ ssize_t ret;
+
+ if (buf == NULL) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, fpga index: %u\n",
+ main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ if (count <= 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, fpga index: %u\n",
+ count, main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FPGA_TYPE, main_dev_id, fpga_index);
+ fpga_type = dfd_ko_cfg_get_item(key);
+ if (fpga_type == NULL) {
+ DBG_FPGA_DEBUG(DBG_VERBOSE,
+ "main_dev_id: %u, fpga%u type config is NULL, try to get fpga type from fpga model\n",
+ main_dev_id, fpga_index);
+ /* Unconfigured fpga_type Obtain the device model from fpga_model */
+ ret = dfd_get_fpga_model(main_dev_id, fpga_index, buf, count);
+ return ret;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "%s\n", fpga_type);
+ snprintf(buf, count, "%s\n", fpga_type);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_fpga_fw_version - Obtain the FPGA firmware version
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index:FPGA number, starting from 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_fw_version(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int rv;
+ uint32_t value;
+
+ if (buf == NULL) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, fpga index: %u\n",
+ main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, fpga index: %u\n",
+ count, main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FPGA_VERSION, main_dev_id, fpga_index);
+ rv = dfd_info_get_int(key, &value, NULL);
+ if (rv < 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "main_dev_id: %u, fpga%u fw config error, key_name: %s, ret: %d\n",
+ main_dev_id, fpga_index, key_to_name(DFD_CFG_ITEM_FPGA_VERSION), rv);
+ return rv;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "main_dev_id: %u, fpga%u firmware version: %x\n",
+ main_dev_id, fpga_index, value);
+ snprintf(buf, count, "0x%08x\n", value);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_fpga_hw_version - Obtain the hardware version of the FPGA
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @index: FPGA number, starting from 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_hw_version(uint8_t main_dev_id, unsigned int fpga_index, char *buf, size_t count)
+{
+
+ if (buf == NULL) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, fpga index: %u\n",
+ main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, fpga index: %u\n",
+ count, main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "main_dev_id: %u, fpga%u hardware version not support\n",
+ main_dev_id, fpga_index);
+ return -DFD_RV_DEV_NOTSUPPORT;
+}
+
+static int value_convert_to_buf(unsigned int value, uint8_t *buf, int len, int pola)
+{
+ int i;
+
+ if ((pola != INFO_POLA_POSI) && (pola != INFO_POLA_NEGA)) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "unsupport pola mode: %d\n", pola);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, len);
+ if (pola == INFO_POLA_POSI) { /* Big-end mode */
+ for (i = 0; i < len; i++) {
+ buf[i] = (value >> ((len - i - 1) * 8)) & 0xff;
+ }
+ } else { /* Small terminal mode */
+ for (i = 0; i < len; i++) {
+ buf[i] = (value >> (i * 8)) & 0xff;
+ }
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_set_fpga_testreg - Sets the value of the FPGA test register
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @fpga_index: FPGA number, starting from 1
+ * @value: Writes the value of the test register
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_set_fpga_testreg(uint8_t main_dev_id, unsigned int fpga_index, unsigned int value)
+{
+ uint64_t key;
+ int ret;
+ uint8_t wr_buf[FPGA_REG_WIDTH_MAX];
+ info_ctrl_t *info_ctrl;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FPGA_TEST_REG, main_dev_id, fpga_index);
+ /* Get the configuration item read and write control variables */
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "main_dev_id: %u, fpga%u get info ctrl failed, key_name: %s\n",
+ main_dev_id, fpga_index, key_to_name(DFD_CFG_ITEM_FPGA_TEST_REG));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ if (info_ctrl->fpath == NULL) {
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "main_dev_id: %u, fpga%u get fpath failed\n", main_dev_id,
+ fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (info_ctrl->len > FPGA_REG_WIDTH_MAX) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "main_dev_id: %u, fpga%u info_ctrl len: %d, unsupport\n",
+ main_dev_id, fpga_index, info_ctrl->len);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ ret = value_convert_to_buf(value, wr_buf, FPGA_REG_WIDTH_MAX, info_ctrl->pola);
+ if (ret < 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "value: 0x%x convert to buf failed, pola:%d, ret: %d\n",
+ value, info_ctrl->pola, ret);
+ return ret;
+ }
+
+ DBG_FPGA_DEBUG(DBG_VERBOSE, "main_dev_id: %u, fpga%u fpath: %s, addr: 0x%x, len: %d value: 0x%x\n",
+ main_dev_id, fpga_index, info_ctrl->fpath, info_ctrl->addr, info_ctrl->len, value);
+ ret = dfd_ko_write_file(info_ctrl->fpath, info_ctrl->addr, wr_buf, info_ctrl->len);
+ if (ret < 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "set fpga test reg failed, ret: %d", ret);
+ return ret;
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fpga_testreg - Read the FPGA test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @fpga_index: FPGA number, starting from 1
+ * @value: Read the test register value
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_get_fpga_testreg(uint8_t main_dev_id, unsigned int fpga_index, int *value)
+{
+ uint64_t key;
+ int ret;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FPGA_TEST_REG, main_dev_id, fpga_index);
+ ret = dfd_info_get_int(key, value, NULL);
+ if (ret < 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "main_dev_id: %u, get fpga%u test reg error, key_name: %s, ret: %d\n",
+ main_dev_id, fpga_index, key_to_name(DFD_CFG_ITEM_FPGA_TEST_REG), ret);
+ return ret;
+ }
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_fpga_testreg_str - Read the FPGA test register value
+ * @main_dev_id: Motherboard :0 Subcard :5
+ * @fpga_index: FPGA number, starting from 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_fpga_testreg_str(uint8_t main_dev_id, unsigned int fpga_index,
+ char *buf, size_t count)
+{
+ int ret, value;
+
+ if (buf == NULL) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "param error, buf is NULL, main_dev_id: %u, fpga index: %u\n",
+ main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_FPGA_DEBUG(DBG_ERROR, "buf size error, count: %lu, main_dev_id: %u, fpga index: %u\n",
+ count, main_dev_id, fpga_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ ret = dfd_get_fpga_testreg(main_dev_id, fpga_index, &value);
+ if (ret < 0) {
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "0x%08x\n", value);
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_led_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_led_driver.c
new file mode 100644
index 000000000000..c66c3150dd79
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_led_driver.c
@@ -0,0 +1,133 @@
+/*
+ * An wb_led_driver driver for led devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_info.h"
+#include "dfd_cfg_adapter.h"
+
+int g_dfd_sysled_dbg_level = 0;
+module_param(g_dfd_sysled_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/**
+ * dfd_get_led_status_value - Get LED light status value
+ * @led_id See the wb_led_t definition
+ * @value 0: Off, 1: green, 2: yellow, 3: red, 4: blue, 5: green, 6: yellow, 7: red
+ * @returns: 0 success, negative value: failed
+ */
+static int dfd_get_led_status_value(uint16_t led_id, uint8_t led_index, int *value)
+{
+ uint64_t key;
+ int ori_value, ret;
+ int *p_decode_value;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_LED_STATUS, led_id, led_index);
+ ret = dfd_info_get_int(key, &ori_value, NULL);
+ if (ret < 0) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "get led status error, key: %s, ret: %d\n",
+ key_to_name(DFD_CFG_ITEM_LED_STATUS), ret);
+ return ret;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_LED_STATUS_DECODE, led_id, ori_value);
+ p_decode_value = dfd_ko_cfg_get_item(key);
+ if (p_decode_value != NULL) {
+ DBG_SYSLED_DEBUG(DBG_VERBOSE, "led id: %u index: %u, ori_value: 0x%x, decode value :0x%x\n",
+ led_id, led_index, ori_value, *p_decode_value);
+ *value = *p_decode_value;
+ return DFD_RV_OK;
+ }
+ return -DFD_RV_INVALID_VALUE;
+}
+
+/**
+ * dfd_get_led_status - Get LED light status
+ * @led_id: led lamp type
+ * @led_index: led light offset
+ * @buf: LED light status receives buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_led_status(uint16_t led_id, uint8_t led_index, char *buf, size_t count)
+{
+ int ret, led_value;
+
+ if (buf == NULL) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "param error, buf is NULL. led_id: %u, led_index: %u\n",
+ led_id, led_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "buf size error, count: %lu, led_id: %u, led_index: %u\n",
+ count, led_id, led_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ mem_clear(buf, count);
+ ret = dfd_get_led_status_value(led_id, led_index, &led_value);
+ if (ret < 0) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "get led status error, ret: %d, led_id: %u, led_index: %u\n",
+ ret, led_id, led_index);
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", led_value);
+}
+
+/**
+ * dfd_set_led_status - Set LED light status
+ * @led_id: led lamp type
+ * @led_index: led light offset
+ * @value: LED light status value
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_set_led_status(uint16_t led_id, uint8_t led_index, int value)
+{
+ uint64_t key;
+ int ret, led_value;
+
+ if (value < 0 || value > 0xff) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "can not set led status value = %d.\n", value);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ DBG_SYSLED_DEBUG(DBG_VERBOSE, "set led id: %u index: %u, status[%d].\n",
+ led_id, led_index, value);
+ ret = dfd_ko_cfg_get_led_status_decode2_by_regval(value, led_id, &led_value);
+ if (ret < 0) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "get led status register error, ret: %d, led_id: %u, value: %d\n",
+ ret, led_id, value);
+ return ret;
+ }
+
+ DBG_SYSLED_DEBUG(DBG_VERBOSE, "get led[%u] index[%u] status[%d] decode value[%d]\n",
+ led_id, led_index, value, led_value);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_LED_STATUS, led_id, led_index);
+ ret = dfd_info_set_int(key, led_value);
+ if (ret < 0) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "set led status error, key_name: %s, ret: %d\n",
+ key_to_name(DFD_CFG_ITEM_LED_STATUS), ret);
+ return ret;
+ }
+
+ return DFD_RV_OK;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_module.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_module.c
new file mode 100644
index 000000000000..69610668a971
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_module.c
@@ -0,0 +1,73 @@
+/*
+ * An wb_module driver for module devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+
+int g_dfd_dbg_level = 0; /* Debug level */
+module_param(g_dfd_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/**
+ * wb_dev_cfg_init - dfd module initialization
+ *
+ * @returns:<0 Failed, otherwise succeeded
+ */
+int32_t wb_dev_cfg_init(void)
+{
+ return dfd_dev_cfg_init();
+}
+
+/**
+ * wb_dev_cfg_exit - dfd module exit
+ *
+ * @returns: void
+ */
+
+void wb_dev_cfg_exit(void)
+{
+ dfd_dev_cfg_exit();
+ return;
+}
+
+/**
+ * dfd_get_dev_number - Get the number of devices
+ * @main_dev_id:Master device number
+ * @minor_dev_id:Secondary device number
+ * @returns: <0 failed, otherwise number of devices is returned
+ */
+int dfd_get_dev_number(unsigned int main_dev_id, unsigned int minor_dev_id)
+{
+ uint64_t key;
+ int dev_num;
+ int *p_dev_num;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_DEV_NUM, main_dev_id, minor_dev_id);
+ p_dev_num = dfd_ko_cfg_get_item(key);
+ if (p_dev_num == NULL) {
+ DBG_DEBUG(DBG_ERROR, "get device number failed, key_name:%s\n",
+ key_to_name(DFD_CFG_ITEM_DEV_NUM));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ dev_num = *p_dev_num;
+ DBG_DEBUG(DBG_VERBOSE, "get device number ok, number:%d\n",dev_num);
+ return dev_num;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_psu_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_psu_driver.c
new file mode 100644
index 000000000000..aad65d282921
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_psu_driver.c
@@ -0,0 +1,950 @@
+/*
+ * An wb_psu_driver driver for psu devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg_info.h"
+#include "dfd_frueeprom.h"
+
+#define PSU_SIZE (256)
+#define WB_GET_PSU_PMBUS_BUS(addr) (((addr) >> 24) & 0xff)
+#define WB_GET_PSU_PMBUS_ADDR(addr) (((addr) >> 8) & 0xffff)
+#define WB_GET_PSU_PMBUS_OFFSET(addr) ((addr) & 0xff)
+#define DFD_PSU_FRU_MODE_E2_STRING "eeprom"
+#define DFD_PSU_FRU_MODE_PMBUS_STRING "pmbus"
+
+#define PSU_PMBUS_POWER_GOOD BIT(11)
+
+typedef enum dfd_psu_pmbus_type_e {
+ DFD_PSU_PMBUS_TYPE_AC = 1,
+ DFD_PSU_PMBUS_TYPE_DC = 2,
+} dfd_psu_pmbus_type_t;
+
+typedef enum dfd_psu_sysfs_type_e {
+ DFD_PSU_SYSFS_TYPE_DC = 0,
+ DFD_PSU_SYSFS_TYPE_AC = 1,
+} dfd_psu_sysfs_type_t;
+
+typedef enum dfd_psu_status_e {
+ DFD_PSU_PRESENT_STATUS = 0,
+ DFD_PSU_OUTPUT_STATUS = 1,
+ DFD_PSU_ALERT_STATUS = 2,
+ DFD_PSU_INPUT_STATUS = 3,
+} dfd_psu_status_t;
+
+typedef enum dfd_psu_alarm_e {
+ DFD_PSU_NOT_OK = 0,
+ DFD_PSU_OK = 1,
+} dfd_psu_alarm_t;
+
+enum knos_alarm {
+ PSU_TERMAL_ERROR = 0x1,
+ PSU_FAN_ERROR = 0x2,
+ PSU_VOL_ERROR = 0x4,
+};
+
+typedef enum psu_fru_mode_e {
+ PSU_FRU_MODE_E2, /* eeprom */
+ PSU_FRU_MODE_PMBUS, /*pmbus*/
+} fan_eeprom_mode_t;
+
+
+/* PMBUS STATUS WORD decode */
+#define PSU_STATUS_WORD_CML (1 << 1)
+#define PSU_STATUS_WORD_TEMPERATURE (1 << 2)
+#define PSU_STATUS_WORD_VIN_UV (1 << 3)
+#define PSU_STATUS_WORD_IOUT_OC (1 << 4)
+#define PSU_STATUS_WORD_VOUT_OV (1 << 5)
+#define PSU_STATUS_WORD_OFF (1 << 6)
+#define PSU_STATUS_WORD_BUSY (1 << 7)
+#define PSU_STATUS_WORD_FANS (1 << 10)
+#define PSU_STATUS_WORD_POWER_GOOD (1 << 11)
+#define PSU_STATUS_WORD_INPUT (1 << 13)
+#define PSU_STATUS_WORD_IOUT (1 << 14)
+#define PSU_STATUS_WORD_VOUT (1 << 15)
+
+#define PSU_VOLTAGE_ERR_OFFSET (PSU_STATUS_WORD_VOUT | PSU_STATUS_WORD_IOUT | \
+ PSU_STATUS_WORD_INPUT | PSU_STATUS_WORD_POWER_GOOD| \
+ PSU_STATUS_WORD_OFF | PSU_STATUS_WORD_VOUT_OV| \
+ PSU_STATUS_WORD_IOUT_OC | PSU_STATUS_WORD_VIN_UV)
+
+int g_dfd_psu_dbg_level = 0;
+module_param(g_dfd_psu_dbg_level, int, S_IRUGO | S_IWUSR);
+
+static int dfd_get_psu_fru_mode(void)
+{
+ uint64_t key;
+ int mode;
+ char *name;
+
+ /* string Type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_FRU_MODE, 0, 0);
+ name = dfd_ko_cfg_get_item(key);
+ if (name == NULL) {
+ /* The default EEPROM format is returned */
+ DFD_PSU_DEBUG(DBG_VERBOSE, "get psu fru mode config fail, key=%s, use default eeprom mode\n",
+ key_to_name(DFD_CFG_ITEM_PSU_FRU_MODE));
+ return PSU_FRU_MODE_E2;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu fru mode %s.\n", name);
+ if (!strncmp(name, DFD_PSU_FRU_MODE_E2_STRING, strlen(DFD_PSU_FRU_MODE_E2_STRING))) {
+ mode = PSU_FRU_MODE_E2;
+ } else if (!strncmp(name, DFD_PSU_FRU_MODE_PMBUS_STRING, strlen(DFD_PSU_FRU_MODE_PMBUS_STRING))) {
+ mode = PSU_FRU_MODE_PMBUS;
+ } else {
+ /* The default EEPROM format is returned */
+ mode = PSU_FRU_MODE_E2;
+ }
+
+ DFD_FAN_DEBUG(DBG_VERBOSE, "psu fru mode %d.\n", mode);
+ return mode;
+}
+
+static char *dfd_get_psu_sysfs_name(void)
+{
+ uint64_t key;
+ char *sysfs_name;
+
+ /* string Type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_SYSFS_NAME, 0, 0);
+ sysfs_name = dfd_ko_cfg_get_item(key);
+ if (sysfs_name == NULL) {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "key_name=%s, sysfs_name is NULL, use default way.\n",
+ key_to_name(DFD_CFG_ITEM_PSU_SYSFS_NAME));
+ } else {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "sysfs_name: %s.\n", sysfs_name);
+ }
+ return sysfs_name;
+}
+
+static void dfd_psu_del_no_print_string(char *buf)
+{
+ int i, len;
+
+ len = strlen(buf);
+ /* Culling noncharacter */
+ for (i = 0; i < len; i++) {
+ if ((buf[i] < 0x21) || (buf[i] > 0x7E)) {
+ buf[i] = '\0';
+ break;
+ }
+ }
+ return;
+}
+
+/**
+ * dfd_get_psu_present_status - Obtain the power supply status
+ * @index: Number of the power supply, starting from 1
+ * return: 0:Not in the position
+ * 1:position
+ * : Negative value - Read failed
+ */
+int dfd_get_psu_present_status(unsigned int psu_index)
+{
+ int present_key, present_status;
+ int ret;
+
+ /* Get presence status */
+ present_key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_STATUS, psu_index, DFD_PSU_PRESENT_STATUS);
+ ret = dfd_info_get_int(present_key, &present_status, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "dfd_get_psu_status error. psu_index: %u, ret: %d\n",
+ psu_index, ret);
+ return ret;
+ }
+
+ return present_status;
+}
+
+/**
+ * dfd_get_psu_present_status_str - Obtain power status
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Gets the value on the pmbus register of the power supply
+ */
+ssize_t dfd_get_psu_present_status_str(unsigned int psu_index, char *buf, size_t count)
+{
+ int ret;
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "params error.psu_index: %u.",psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n",
+ count, psu_index);
+ return -EINVAL;
+ }
+
+ ret = dfd_get_psu_present_status(psu_index);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu status error, ret: %d, psu_index: %u\n", ret, psu_index);
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", ret);
+}
+
+ssize_t dfd_get_psu_pmbus_status(unsigned int psu_index, char *buf, size_t count)
+{
+ int key;
+ int ret;
+
+ /* PMBUS STATUS WORD (0x79) */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_HWMON_PSU, psu_index, PSU_HW_STATUS);
+ ret = dfd_info_get_sensor(key, buf, count, NULL);
+
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus status info failed, key: 0x%08x, ret: %d\n",
+ psu_index, DFD_CFG_ITEM_HWMON_PSU, ret);
+ } else {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, pmbus_data = %s \n", psu_index, buf);
+ }
+ return ret;
+}
+
+/**
+ * dfd_get_psu_hw_status_str - get psu status str
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Gets the value on the pmbus register of the power supply
+ */
+ssize_t dfd_get_psu_hw_status_str(unsigned int psu_index, char *buf, size_t count)
+{
+ int ret;
+ int status_word;
+ int status;
+ int output_key, output_status;
+ int alert_key, alert_status;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "params error, psu_index: %u", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n",
+ count, psu_index);
+ return -EINVAL;
+ }
+
+ /* get psu present status first */
+ ret = dfd_get_psu_present_status(psu_index);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu present status error, ret: %d, psu_index: %u\n", ret, psu_index);
+ return ret;
+ }
+ if (ret == PSU_STATUS_ABSENT) {
+ return (ssize_t)snprintf(buf, count, "%d\n", PSU_STATUS_ABSENT);
+ }
+
+ /* get psu alert and power status from cpld */
+ output_key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_STATUS, psu_index, DFD_PSU_OUTPUT_STATUS);
+ alert_key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_STATUS, psu_index, DFD_PSU_ALERT_STATUS);
+ ret = dfd_info_get_int(output_key, &output_status, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu output_key error, ret: %d, psu_index: %u\n",
+ ret, psu_index);
+ return ret;
+ }
+ ret = dfd_info_get_int(alert_key, &alert_status, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu alert_key error, ret: %d, psu_index: %u\n",
+ ret, psu_index);
+ return ret;
+ }
+ DFD_PSU_DEBUG(DBG_VERBOSE, "get psu %u alert: %u, output: %u.\n", psu_index, alert_status, output_status);
+ /* if cpld status not ok */
+ if (!alert_status || !output_status) {
+ /* jduge psu status from psu pmbus 0x79 */
+ ret = dfd_get_psu_pmbus_status(psu_index, buf, count);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu pmbus status error, ret: %d, psu_index: %u\n", ret, psu_index);
+ return ret;
+ } else {
+ ret = kstrtoint(buf, 0, &status_word);
+ if (ret) {
+ DFD_PSU_DEBUG(DBG_ERROR, "invalid value: %s \n", buf);
+ return -EINVAL;
+ }
+ DFD_PSU_DEBUG(DBG_VERBOSE, "get psu %u statu reg value: %u.\n", psu_index, status_word);
+ status = (status_word & PSU_PMBUS_POWER_GOOD) ? PSU_STATUS_FAIL : PSU_STATUS_WARN;
+ }
+ } else {
+ status = PSU_STATUS_PRESENT;
+ }
+
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", status);
+}
+
+/**
+ * dfd_get_psu_status_pmbus_str - Gets the value on the pmbus register of the power supply
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_status_pmbus_str(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+ int pmbus_data;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u\n", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n", count, psu_index);
+ return -EINVAL;
+ }
+
+ /* Gets the status from the pmbus register of the power supply */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_PMBUS_REG, psu_index, PSU_SENSOR_NONE);
+ ret = dfd_info_get_int(key, &pmbus_data, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus status info failed, key_name: %s, ret: %d\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_PMBUS_REG), ret);
+ return ret;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", pmbus_data);
+}
+
+/**
+ * dfd_get_psu_fan_speed_cal_str - Obtain the formula for calculating the speed of the power supply
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+static int dfd_get_psu_fan_speed_cal_str(int power_type, char *psu_buf, int buf_len)
+{
+ uint64_t key;
+ char *speed_cal;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_FAN_SPEED_CAL, power_type, 0);
+ speed_cal = dfd_ko_cfg_get_item(key);
+ if (speed_cal == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "config error, get psu speed cal error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_FAN_SPEED_CAL));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ mem_clear(psu_buf, buf_len);
+ strlcpy(psu_buf, speed_cal, buf_len);
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu speed cal match ok, speed_cal: %s\n", psu_buf);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_psu_out_status_str - Obtain the output power status
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_out_status_str(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+ int pmbus_data;
+ int output_status;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u\n", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n", count, psu_index);
+ return -EINVAL;
+ }
+
+ /* Gets the status from the pmbus register of the power supply */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_PMBUS_REG, psu_index, PSU_OUT_STATUS);
+ ret = dfd_info_get_int(key, &pmbus_data, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus status info failed, key_name: %s, ret: %d\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_PMBUS_REG), ret);
+ return ret;
+ }
+
+ output_status = DFD_PSU_OK;
+ if (pmbus_data & (PSU_STATUS_WORD_INPUT | PSU_STATUS_WORD_OFF | PSU_STATUS_WORD_POWER_GOOD)) {
+ /* The judgment logic of no power is consistent with that of Baidu sysfs */
+ output_status = DFD_PSU_NOT_OK;
+ }
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", output_status);
+}
+
+/**
+ * dfd_psu_product_name_decode - Power name conversion
+ * @power_type: Power supply type
+ * @psu_buf: Power name buffer
+ * @buf_len: psu_buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+static int dfd_psu_product_name_decode(int power_type, char *psu_buf, int buf_len)
+{
+ uint64_t key;
+ char *p_decode_name;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_DECODE_POWER_NAME, power_type, 0);
+ p_decode_name = dfd_ko_cfg_get_item(key);
+ if (p_decode_name == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "config error, get psu decode name error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_DECODE_POWER_NAME));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ mem_clear(psu_buf, buf_len);
+ strlcpy(psu_buf, p_decode_name, buf_len);
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu name match ok, display psu name: %s\n", psu_buf);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_psu_fan_direction_decode - Power duct type conversion
+ * @power_type: Power supply type
+ * @psu_buf: Power name buffer
+ * @buf_len: psu_buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+static int dfd_psu_fan_direction_decode(int power_type, char *psu_buf, int buf_len)
+{
+ uint64_t key;
+ char *p_decode_direction;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_DECODE_POWER_FAN_DIR, power_type, 0);
+ p_decode_direction = dfd_ko_cfg_get_item(key);
+ if (p_decode_direction == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "config error, get psu decode direction error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_DECODE_POWER_FAN_DIR));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ mem_clear(psu_buf, buf_len);
+ snprintf(psu_buf, buf_len, "%d", *p_decode_direction);
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu%u fan direction match ok, display psu direction: %s\n",
+ power_type, psu_buf);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_psu_max_output_power - Rated power of supply
+ * @power_type: Power supply type
+ * @psu_buf: Data buffer
+ * @buf_len: psu_buf length
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+static int dfd_psu_max_output_power(int power_type, char *psu_buf, int buf_len)
+{
+ uint64_t key;
+ int value;
+ int *p_power_max_output_power;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_POWER_RSUPPLY, power_type, 0);
+ p_power_max_output_power = dfd_ko_cfg_get_item(key);
+ if (p_power_max_output_power == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "config error, get psu input type error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_POWER_RSUPPLY));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ value = *p_power_max_output_power;
+ mem_clear(psu_buf, buf_len);
+ snprintf(psu_buf, buf_len, "%d", value);
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu name %s match max output power %d\n", psu_buf, value);
+ return DFD_RV_OK;
+}
+
+static int dfd_get_psu_fru_pmbus(unsigned int psu_index, uint8_t cmd, char *buf, size_t buf_len)
+{
+ uint64_t key;
+ int rv, len;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_FRU_PMBUS, psu_index, cmd);
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu index: %d, cmd: %d, key_name: %s\n",
+ psu_index, cmd, key_to_name(DFD_CFG_ITEM_PSU_FRU_PMBUS));
+
+ rv = dfd_info_get_sensor(key, buf, buf_len, NULL);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu fru info by pmbus failed, key_name: %s, rv: %d\n",
+ key_to_name(DFD_CFG_ITEM_PSU_FRU_PMBUS), rv);
+ } else {
+ len = strlen(buf);
+ if (len > 0 && buf[len - 1] == '\n') {
+ buf[len - 1] = '\0';
+ }
+ DFD_PSU_DEBUG(DBG_VERBOSE, "get psu fru info by pmbus success, value: %s\n", buf);
+ }
+ return rv;
+}
+
+static int dfd_get_psu_type(unsigned int psu_index, dfd_i2c_dev_t *i2c_dev, int *power_type,
+ const char *sysfs_name, int fru_mode)
+{
+ int rv;
+ char psu_buf[PSU_SIZE];
+
+ mem_clear(psu_buf, sizeof(psu_buf));
+ if (fru_mode == PSU_FRU_MODE_PMBUS) {
+ rv = dfd_get_psu_fru_pmbus(psu_index, DFD_DEV_INFO_TYPE_PART_NUMBER, psu_buf, PSU_SIZE);
+ } else {
+ rv = dfd_get_fru_data(i2c_dev->bus, i2c_dev->addr, DFD_DEV_INFO_TYPE_PART_NUMBER, psu_buf,
+ PSU_SIZE, sysfs_name);
+ }
+
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu type from eeprom read failed, rv: %d\n", rv);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "%s\n", psu_buf);
+ dfd_psu_del_no_print_string(psu_buf);
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "dfd_psu_product_name_decode get psu name %s\n", psu_buf);
+ rv = dfd_ko_cfg_get_power_type_by_name((char *)psu_buf, power_type);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get power type by name[%s] fail, rv: %d\n", psu_buf, rv);
+ return -DFD_RV_NO_NODE;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "get psu%u return power_type[0x%x]\n", psu_index, *power_type);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_psu_info - Get Power Information
+ * @index: Number of the power supply, starting from 1
+ * @cmd: Power supply information Type, power supply name :2, power supply serial number :3, power supply hardware version :5
+ * @buf: Receive buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_psu_info(unsigned int psu_index, uint8_t cmd, char *buf, size_t count)
+{
+ uint64_t key;
+ int rv;
+ char psu_buf[PSU_SIZE];
+ dfd_i2c_dev_t *i2c_dev;
+ int power_type;
+ int fru_mode;
+ const char *sysfs_name;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u, cmd: 0x%x\n", psu_index, cmd);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u, cmd: 0x%x\n",
+ count, psu_index, cmd);
+ return -EINVAL;
+ }
+
+ fru_mode = dfd_get_psu_fru_mode();
+ mem_clear(buf, count);
+ mem_clear(psu_buf, PSU_SIZE);
+ if (fru_mode == PSU_FRU_MODE_E2) {
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_OTHER_I2C_DEV, WB_MAIN_DEV_PSU, psu_index);
+ i2c_dev = dfd_ko_cfg_get_item(key);
+ if (i2c_dev == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu i2c dev config error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_OTHER_I2C_DEV));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ sysfs_name = dfd_get_psu_sysfs_name();
+ }
+
+ /* Power E2 product name conversion */
+ if (cmd == DFD_DEV_INFO_TYPE_PART_NAME) {
+ rv = dfd_get_psu_type(psu_index, i2c_dev, &power_type, sysfs_name, fru_mode);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu get type error, rv: %d\n", rv);
+ return -EIO;
+ }
+ rv = dfd_psu_product_name_decode(power_type, psu_buf, PSU_SIZE);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu name decode error, power_type[0x%x] rv: %d\n",
+ power_type, rv);
+ return -EIO;
+ }
+ } else if (cmd == DFD_DEV_INFO_TYPE_FAN_DIRECTION) {
+ rv = dfd_get_psu_type(psu_index, i2c_dev, &power_type, sysfs_name, fru_mode);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu get type error, rv: %d\n", rv);
+ return -EIO;
+ }
+ rv = dfd_psu_fan_direction_decode(power_type, psu_buf, PSU_SIZE);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu input type decode error, power_type[0x%x] rv: %d\n",
+ power_type, rv);
+ return -EIO;
+ }
+ } else if (cmd == DFD_DEV_INFO_TYPE_MAX_OUTPUT_POWRER) {
+ rv = dfd_get_psu_type(psu_index, i2c_dev, &power_type, sysfs_name, fru_mode);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu get type error, rv:%d\n", rv);
+ return -EIO;
+ }
+ rv = dfd_psu_max_output_power(power_type, psu_buf, PSU_SIZE);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu max ouput power error, power_type[0x%x] rv: %d\n",
+ power_type, rv);
+ return -EIO;
+ }
+ } else if (cmd == DFD_DEV_INFO_TYPE_SPEED_CAL) {
+ rv = dfd_get_psu_type(psu_index, i2c_dev, &power_type, sysfs_name, fru_mode);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu get type error, rv:%d\n", rv);
+ return -EIO;
+ }
+ rv = dfd_get_psu_fan_speed_cal_str(power_type, psu_buf, PSU_SIZE);
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu fan speed cal error, power_type[0x%x] rv: %d\n",
+ power_type, rv);
+ return -EIO;
+ }
+ } else {
+ if (fru_mode == PSU_FRU_MODE_PMBUS) {
+ rv = dfd_get_psu_fru_pmbus(psu_index, cmd, psu_buf, PSU_SIZE);
+ } else {
+ rv = dfd_get_fru_data(i2c_dev->bus, i2c_dev->addr, cmd, psu_buf, PSU_SIZE, sysfs_name);
+ }
+ if (rv < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "psu eeprom read failed, rv: %d\n", rv);
+ return -EIO;
+ }
+ }
+
+ snprintf(buf, count, "%s\n", psu_buf);
+ return strlen(buf);
+}
+
+/**
+ * dfd_get_psu_input_type - Obtain the power input type
+ * @index: Number of the power supply, starting from 1
+ * @buf: Receive buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_psu_input_type(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+ int data;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u\n", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n", count, psu_index);
+ return -EINVAL;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_PMBUS_REG, psu_index, PSU_IN_TYPE);
+ ret = dfd_info_get_int(key, &data, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus status info failed, key_name: %s, ret: %d\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_PMBUS_REG), ret);
+ return ret;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, pmbus_data = 0x%x \n", psu_index, data);
+
+ if (data == DFD_PSU_PMBUS_TYPE_AC) {
+ return snprintf(buf, count, "%d\n", DFD_PSU_SYSFS_TYPE_AC);
+ } else if (data == DFD_PSU_PMBUS_TYPE_DC) {
+ return snprintf(buf, count, "%d\n", DFD_PSU_SYSFS_TYPE_DC);
+ } else {
+ DFD_PSU_DEBUG(DBG_WARN, "get psu%u input type data[%u] unknow, ret: %d\n",
+ psu_index, data, ret);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus type data[%u] unknow, ret: %d\n",
+ psu_index, data, ret);
+ return -EIO;
+}
+
+/**
+ * dfd_get_psu_in_status_str - Obtain the input power status
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_in_status_str(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+ int pmbus_data;
+ int input_status;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u\n", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n", count, psu_index);
+ return -EINVAL;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_PMBUS_REG, psu_index, PSU_IN_STATUS);
+ ret = dfd_info_get_int(key, &pmbus_data, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus status info failed, key_name: %s, ret: %d\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_PMBUS_REG), ret);
+ return ret;
+ }
+
+ input_status = DFD_PSU_OK;
+ if (pmbus_data & PSU_STATUS_WORD_INPUT) {
+ /* no power judgment logic, according to the opinion only bit13 judgment */
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, no power, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+ input_status = DFD_PSU_NOT_OK;
+ }
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", input_status);
+}
+
+ssize_t dfd_get_psu_alarm_status(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+ int pmbus_data;
+ int alarm;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u\n", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n", count, psu_index);
+ return -EINVAL;
+ }
+
+ /* PMBUS STATUS WORD (0x79) */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_PMBUS_REG, psu_index, PSU_OUT_STATUS);
+ ret = dfd_info_get_int(key, &pmbus_data, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus status info failed, key_name: %s, ret: %d\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_PMBUS_REG), ret);
+ return ret;
+ }
+
+ alarm = 0;
+ if (pmbus_data & PSU_STATUS_WORD_TEMPERATURE) {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu%d PSU_TERMAL_ERROR, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+ alarm |= PSU_TERMAL_ERROR;
+ }
+
+ if (pmbus_data & PSU_STATUS_WORD_FANS) {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu%d PSU_FAN_ERROR, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+ alarm |= PSU_FAN_ERROR;
+ }
+
+ if (pmbus_data & PSU_VOLTAGE_ERR_OFFSET) {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu%d PSU_VOL_ERROR, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+ alarm |= PSU_VOL_ERROR;
+ }
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, pmbus_data = 0x%x \n", psu_index, pmbus_data);
+
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", alarm);
+}
+
+/**
+ * dfd_get_psu_fan_ratio_str - Gets the target fan rotation rate
+ * @index: Number of the power supply, starting from 1
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_psu_fan_ratio_str(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+ int pmbus_data;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u\n", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n", count, psu_index);
+ return -EINVAL;
+ }
+
+ /* Gets the status from the pmbus register of the power supply */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_PMBUS_REG, psu_index, PSU_FAN_RATIO);
+ ret = dfd_info_get_int(key, &pmbus_data, NULL);
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus fan ratio info failed, key_name: %s, ret: %d\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_PMBUS_REG), ret);
+ return ret;
+ }
+
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", pmbus_data);
+}
+
+ssize_t dfd_get_psu_threshold_str(unsigned int psu_index, unsigned int type, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf is NULL, psu index: %u\n", psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n", count, psu_index);
+ return -EINVAL;
+ }
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_HWMON_PSU, psu_index, type);
+ ret = dfd_info_get_sensor(key, buf, count, NULL);
+ if (ret < 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "get psu sensor info error, key_name: %s, ret: %d\n",
+ key_to_name(DFD_CFG_ITEM_HWMON_PSU), ret);
+ } else {
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "get psu sensor info success, value: %s\n", buf);
+ }
+ return ret;
+}
+
+ssize_t dfd_get_psu_blackbox(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ ssize_t rd_len;
+ char *blackbox_path;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "params error.psu_index: %u.",psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n",
+ count, psu_index);
+ return -EINVAL;
+ }
+
+ /* Obtain the blackbox_info path*/
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_BLACKBOX_INFO, psu_index, 0);
+ blackbox_path = dfd_ko_cfg_get_item(key);
+ if (blackbox_path == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u blackbox_info path error, key_name: %s\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_BLACKBOX_INFO));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, blackbox_info path: %s\n", psu_index, blackbox_path);
+
+ mem_clear(buf, count);
+ rd_len = dfd_ko_read_file(blackbox_path, 0, buf, count);
+ if (rd_len < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "read psu%u blackbox info failed, blackbox_info path: %s, ret: %ld\n",
+ psu_index, blackbox_path, rd_len);
+ } else {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "read psu%u blackbox info success, blackbox_info path: %s, rd_len: %ld\n",
+ psu_index, blackbox_path, rd_len);
+ }
+
+ return rd_len;
+}
+
+ssize_t dfd_get_psu_pmbus(unsigned int psu_index, char *buf, size_t count)
+{
+ uint64_t key;
+ ssize_t rd_len;
+ char *pmbus_info_path;
+
+ if (buf == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "params error.psu_index: %u.",psu_index);
+ return -EINVAL;
+ }
+ if (count <= 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "buf size error, count: %lu, psu index: %u\n",
+ count, psu_index);
+ return -EINVAL;
+ }
+
+ /* Obtain the pmbus_info path*/
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_PMBUS_INFO, psu_index, 0);
+ pmbus_info_path = dfd_ko_cfg_get_item(key);
+ if (pmbus_info_path == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u pmbus_info path error, key_name: %s\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_PMBUS_INFO));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, pmbus_info path: %s\n", psu_index, pmbus_info_path);
+
+ mem_clear(buf, count);
+ rd_len = dfd_ko_read_file(pmbus_info_path, 0, buf, count);
+ if (rd_len < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "read psu%u pmbus info failed, pmbus_info path: %s, ret: %ld\n",
+ psu_index, pmbus_info_path, rd_len);
+ } else {
+ DFD_PSU_DEBUG(DBG_VERBOSE, "read psu%u pmbus info success, pmbus_info path: %s, rd_len: %ld\n",
+ psu_index, pmbus_info_path, rd_len);
+ }
+
+ return rd_len;
+}
+
+int dfd_clear_psu_blackbox(unsigned int psu_index, uint8_t value)
+{
+ uint64_t key;
+ int ret;
+ char *clear_blackbox_info_path;
+ uint8_t wr_buf[INFO_INT_MAX_LEN];
+
+ /* Obtain the clear_blackbox path*/
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PSU_CLEAR_BLACKBOX, psu_index, 0);
+ clear_blackbox_info_path = dfd_ko_cfg_get_item(key);
+ if (clear_blackbox_info_path == NULL) {
+ DFD_PSU_DEBUG(DBG_ERROR, "get psu%u clear blackbox path error, key_name: %s\n",
+ psu_index, key_to_name(DFD_CFG_ITEM_PSU_CLEAR_BLACKBOX));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, clear blackbox path: %s, write value: %u\n",
+ psu_index, clear_blackbox_info_path, value);
+
+ mem_clear(wr_buf, sizeof(wr_buf));
+ snprintf(wr_buf, sizeof(wr_buf), "%u", value);
+ ret = dfd_ko_write_file(clear_blackbox_info_path, 0, wr_buf, strlen(wr_buf));
+ if (ret < 0) {
+ DFD_PSU_DEBUG(DBG_ERROR, "clear psu%u blackbox info failed, ret: %d\n", psu_index, ret);
+ return ret;
+ }
+
+ DFD_PSU_DEBUG(DBG_VERBOSE, "psu_index: %u, clear blackbox info success\n", psu_index);
+ return DFD_RV_OK;
+}
+
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_sensors_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_sensors_driver.c
new file mode 100644
index 000000000000..c7342de6e3e2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_sensors_driver.c
@@ -0,0 +1,345 @@
+/*
+ * An wb_sensors_driver driver for snesors devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg_info.h"
+#include "dfd_frueeprom.h"
+#include "dfd_cfg_file.h"
+
+#define DFD_GET_TEMP_SENSOR_KEY1(dev_index, temp_index) \
+ (((dev_index & 0xff) << 8) | (temp_index & 0xff))
+#define DFD_GET_TEMP_SENSOR_KEY2(main_dev_id, temp_type) \
+ (((main_dev_id & 0x0f) << 4) | (temp_type & 0x0f))
+#define DFD_FORMAT_STR_MAX_LEN (32)
+
+int g_dfd_sensor_dbg_level = 0;
+module_param(g_dfd_sensor_dbg_level, int, S_IRUGO | S_IWUSR);
+
+static int dfd_deal_hwmon_buf(uint8_t *buf, int buf_len, uint8_t *buf_new, int *buf_len_new,
+ info_ctrl_t *info_ctrl, int coefficient, int addend)
+{
+ int i, tmp_len;
+ int exp, decimal, divisor;
+ int org_value, tmp_value;
+ int div_result, div_mod;
+ char fmt_str[DFD_FORMAT_STR_MAX_LEN];
+
+ exp = info_ctrl->int_cons; /* Numerical conversion index */
+ decimal = info_ctrl->bit_offset; /* Decimal point retention number */
+
+ /* No conversion is required, just copy the value */
+ if ((exp <= 0) && (coefficient == 1) && (addend == 0)) {
+ DBG_DEBUG(DBG_VERBOSE, "exponent %d, coefficient: %d, addend: %d, don't need transform, buf_len: %d, buf_len_new: %d\n",
+ exp, coefficient, addend, buf_len, *buf_len_new);
+ snprintf(buf_new, *buf_len_new, "%s", buf);
+ *buf_len_new = strlen(buf_new);
+ return DFD_RV_OK;
+ }
+
+ divisor = 1;
+ for (i = 0; i < exp; i++) {
+ divisor *= 10;
+ }
+ org_value = simple_strtol(buf, NULL, 10);
+ DBG_DEBUG(DBG_VERBOSE, "original value: %d, exp: %d, divisor: %d, decimal: %d, coefficient: %d, addend: %d\n",
+ org_value, exp, divisor, decimal, coefficient, addend);
+
+ org_value = (org_value + addend) * coefficient;
+ if (org_value < 0) {
+ tmp_value = 0 - org_value;
+ } else {
+ tmp_value = org_value;
+ }
+ div_result = tmp_value / divisor;
+ div_mod = tmp_value % divisor;
+ DBG_DEBUG(DBG_VERBOSE, "tmp_value: %d, divisor: %d, div_result: %d, div_mod: %d\n",
+ tmp_value, divisor, div_result, div_mod);
+ /* don't need to keep the decimal, just round it */
+ if (decimal == 0) {
+ snprintf(buf_new, *buf_len_new, "%d\n", div_result);
+ *buf_len_new = strlen(buf_new);
+ return DFD_RV_OK;
+ }
+ mem_clear(fmt_str, sizeof(fmt_str));
+ if (org_value < 0) {
+ snprintf(fmt_str, sizeof(fmt_str), "-%%d.%%0%dd\n",exp);
+ } else {
+ snprintf(fmt_str, sizeof(fmt_str), "%%d.%%0%dd\n",exp);
+ }
+ DBG_DEBUG(DBG_VERBOSE, "format string: %s",fmt_str);
+ snprintf(buf_new, *buf_len_new, fmt_str, div_result, div_mod);
+ *buf_len_new = strlen(buf_new);
+ tmp_len = *buf_len_new;
+ /* Keep decimal places only when the number of decimal places is reduced */
+ if (decimal > 0) {
+ for (i = 0; i < *buf_len_new; i++) {
+ if (buf_new[i] == '.') {
+ if (i + decimal + 2 <= *buf_len_new) {
+ buf_new[i + decimal + 1 ] = '\n';
+ buf_new[i + decimal + 2 ] = '\0';
+ *buf_len_new = strlen(buf_new);
+ DBG_DEBUG(DBG_VERBOSE, "deal decimal[%d] ok, str len:%d, value:%s\n",
+ decimal, *buf_len_new, buf_new);
+ }
+ break;
+ }
+ }
+ if (tmp_len == *buf_len_new) {
+ DBG_DEBUG(DBG_WARN, "deal decimal[%d] failed, use original value:%s\n", decimal,
+ buf_new);
+ }
+ }
+ return DFD_RV_OK;
+}
+
+static int dfd_get_sensor_info(uint8_t main_dev_id, uint8_t dev_index, uint8_t sensor_type,
+ uint8_t sensor_index, uint8_t sensor_attr, char *buf, size_t count)
+{
+ uint64_t key;
+ uint16_t key_index1;
+ uint8_t key_index2;
+ int rv;
+ info_hwmon_buf_f pfunc;
+
+ key_index1 = DFD_GET_TEMP_SENSOR_KEY1(dev_index, sensor_index);
+ key_index2 = DFD_GET_TEMP_SENSOR_KEY2(main_dev_id, sensor_attr);
+ if (sensor_type == WB_MINOR_DEV_TEMP) {
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_HWMON_TEMP, key_index1, key_index2);
+ } else if (sensor_type == WB_MINOR_DEV_IN) {
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_HWMON_IN, key_index1, key_index2);
+ } else if (sensor_type == WB_MINOR_DEV_CURR) {
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_HWMON_CURR, key_index1, key_index2);
+ } else {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "Unknow sensor type: %u\n",sensor_type);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "main_dev_id: %u, dev_index: 0x%x, sensor_index: 0x%x, \
+ sensor_attr: 0x%x, key: 0x%08llx\n", main_dev_id, dev_index, sensor_index, sensor_attr, key);
+
+ pfunc = dfd_deal_hwmon_buf;
+ rv = dfd_info_get_sensor(key, buf, count, pfunc);
+ return rv;
+}
+
+/**
+ * dfd_get_temp_info - Get temperature information
+ * @main_dev_id: Motherboard :0 Power supply :2 subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1/psu1
+ * @temp_index: Temperature index, starting at 1
+ * @temp_type: Read type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_temp_info(uint8_t main_dev_id, uint8_t dev_index, uint8_t temp_index,
+ uint8_t temp_attr, char *buf, size_t count)
+{
+ int rv;
+
+ if (buf == NULL) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "param error, buf is NULL\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ if (count <= 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "buf size error, count: %lu\n", count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ rv = dfd_get_sensor_info(main_dev_id, dev_index, WB_MINOR_DEV_TEMP, temp_index, temp_attr,
+ buf, count);
+ if (rv < 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "get temp info error, rv: %d\n", rv);
+ } else {
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "get temp info success, value: %s\n", buf);
+ }
+ return rv;
+}
+
+/**
+ * dfd_get_voltage_info - Get voltage information
+ * @main_dev_id: Motherboard :0 Power supply :2 subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1
+ * @in_index: Voltage index, starting at 1
+ * @in_type: Voltage type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_voltage_info(uint8_t main_dev_id, uint8_t dev_index, uint8_t in_index,
+ uint8_t in_attr, char *buf, size_t count)
+{
+ int rv;
+
+ if (buf == NULL) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "param error buf is NULL.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "buf size error, count: %lu\n", count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ rv = dfd_get_sensor_info(main_dev_id, dev_index, WB_MINOR_DEV_IN, in_index, in_attr, buf,
+ count);
+ if (rv < 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "get voltage info error, rv: %d\n", rv);
+ } else {
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "get voltage info success, value: %s\n", buf);
+ }
+ return rv;
+}
+
+/**
+ * dfd_get_current_info - Get current information
+ * @main_dev_id: Motherboard :0 Power supply :2 subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1
+ * @in_index: Current index, starting at 1
+ * @in_type: Current type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_current_info(uint8_t main_dev_id, uint8_t dev_index, uint8_t curr_index,
+ uint8_t curr_attr, char *buf, size_t count)
+{
+ int rv;
+
+ if (buf == NULL) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "param error buf is NULL.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "buf size error, count: %lu\n", count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ rv = dfd_get_sensor_info(main_dev_id, dev_index, WB_MINOR_DEV_CURR, curr_index, curr_attr,
+ buf, count);
+ if (rv < 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "get current info error, rv: %d\n", rv);
+ } else {
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "get current info success, value: %s\n", buf);
+ }
+ return rv;
+}
+
+/**
+ * dfd_get_psu_sensor_info - Obtain PMBUS information about the power supply
+ * @psu_index: Power index, starting at 1
+ * @sensor_type: Type of the obtained pmbus information
+ * @buf: pmbus results are stored in buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_psu_sensor_info(uint8_t psu_index, uint8_t sensor_type, char *buf, size_t count)
+{
+ uint64_t key;
+ int rv;
+ info_hwmon_buf_f pfunc;
+
+ if (buf == NULL) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "param error. buf is NULL.\n");
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "buf size error, count: %lu\n", count);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_HWMON_PSU, psu_index, sensor_type);
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "psu index: %d, sensor type: %d, key_name: %s,\n", psu_index,
+ sensor_type, key_to_name(DFD_CFG_ITEM_HWMON_PSU));
+ pfunc = dfd_deal_hwmon_buf;
+ rv = dfd_info_get_sensor(key, buf, count, pfunc);
+ if (rv < 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "get psu sensor info error, key_name: %s, rv: %d\n",
+ key_to_name(DFD_CFG_ITEM_HWMON_PSU), rv);
+ } else {
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "get psu sensor info success, value: %s\n", buf);
+ }
+ return rv;
+}
+
+/**
+ * dfd_get_main_board_monitor_flag - Get Monitor flag info
+ * @main_dev_id: Motherboard :0 Power supply :2 subcard :5
+ * @dev_index: If no device index exists, the value is 0, and 1 indicates slot1
+ * @sensor_type: Type of the obtained pmbus information
+ * @in_type: Voltage type,1:alias 2:type 3:max 4:max_hyst 5:min 6:input
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+int dfd_get_main_board_monitor_flag(uint8_t main_dev_id, uint8_t dev_index, uint8_t sensor_type,
+ uint8_t sensor_index, char *buf, size_t count)
+{
+ uint64_t key;
+ uint16_t key_index1;
+ uint8_t key_index2;
+ int rv, sensor_type_key, decode_key;
+ int data;
+ info_ctrl_t *info_ctrl;
+ int *p_decode_value;
+
+ key_index1 = DFD_GET_TEMP_SENSOR_KEY1(dev_index, sensor_index);
+ key_index2 = DFD_GET_TEMP_SENSOR_KEY2(main_dev_id, 0); /* 4bytes. currently low bytes is 0. */
+ if (sensor_type == WB_MINOR_DEV_TEMP) {
+ sensor_type_key = DFD_CFG_ITEM_HWMON_TEMP_MONITOR_FLAG;
+ decode_key = DFD_CFG_ITEM_HWMON_TEMP_MONITOR_DC;
+ } else if (sensor_type == WB_MINOR_DEV_IN) {
+ sensor_type_key = DFD_CFG_ITEM_HWMON_IN_MONITOR_FLAG;
+ decode_key = DFD_CFG_ITEM_HWMON_IN_MONITOR_FLAG_DC;
+ } else if (sensor_type == WB_MINOR_DEV_CURR) {
+ sensor_type_key = DFD_CFG_ITEM_HWMON_CURR_MONITOR_FLAG;
+ decode_key = DFD_CFG_ITEM_HWMON_CURR_MONITOR_FLAG_DC;
+ } else {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "Unknow sensor type: %u\n",sensor_type);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ key = DFD_CFG_KEY(sensor_type_key, key_index1, key_index2);
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DBG_DEBUG(DBG_VERBOSE, "get info ctrl failed, key=0x%08llx\n", key);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", WB_SENSOR_MONITOR_YES);
+ }
+
+ rv = dfd_info_get_int(key, &data, NULL);
+ if (rv < 0) {
+ DFD_SENSOR_DEBUG(DBG_ERROR, "get monitor flag error, key_name: %s, rv: %d\n",
+ key_to_name(sensor_type_key), rv);
+ return rv;
+ }
+
+ key = DFD_CFG_KEY(decode_key, key_index1, data);
+ p_decode_value = dfd_ko_cfg_get_item(key);
+ if (p_decode_value == NULL) {
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "status needn't decode. value:0x%x\n", data);
+ } else {
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "ori_value:0x%x, decoded value:0x%x\n", data, *p_decode_value);
+ data = *p_decode_value;
+ }
+
+ DFD_SENSOR_DEBUG(DBG_VERBOSE, "main_dev_id: %u, dev_index: 0x%x, sensor_index: 0x%x, \
+ key_name: %s, data = %d\n", main_dev_id, dev_index, sensor_index, key_to_name(sensor_type_key), data);
+
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", data);
+}
+
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_sff_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_sff_driver.c
new file mode 100644
index 000000000000..1b55989ebde0
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_sff_driver.c
@@ -0,0 +1,143 @@
+/*
+ * An wb_sff_driver driver for sff devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_info.h"
+#include "dfd_cfg_adapter.h"
+
+int g_dfd_sff_dbg_level = 0;
+module_param(g_dfd_sff_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/**
+ * dfd_set_sff_cpld_info - Example Set the CPLD register status of the optical module
+ * @sff_index: Optical module number, starting from 1
+ * @cpld_reg_type: Optical module CPLD register type
+ * @value: Writes the value to the register
+ * return: Success :0
+ * : Failed: A negative value is returned
+ */
+int dfd_set_sff_cpld_info(unsigned int sff_index, int cpld_reg_type, int value)
+{
+ uint64_t key;
+ int ret;
+
+ if ((value != 0) && (value != 1)) {
+ DFD_SFF_DEBUG(DBG_ERROR, "sff%u cpld reg type %d, can't set invalid value: %d\n",
+ sff_index, cpld_reg_type, value);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_SFF_CPLD_REG, sff_index, cpld_reg_type);
+ ret = dfd_info_set_int(key, value);
+ if (ret < 0) {
+ DFD_SFF_DEBUG(DBG_ERROR, "set sff%u cpld reg type %d error, key_name: %s, ret: %d.\n",
+ sff_index, cpld_reg_type, key_to_name(DFD_CFG_ITEM_SFF_CPLD_REG), ret);
+ return ret;
+ }
+
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_sff_cpld_info - Obtain the CPLD register status of the optical module
+ * @sff_index: Optical module number, starting from 1
+ * @cpld_reg_type: Optical module CPLD register type
+ * @buf: Optical module E2 receives information from buf
+ * @count: buf length
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_sff_cpld_info(unsigned int sff_index, int cpld_reg_type, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret, value;
+
+ if (buf == NULL) {
+ DFD_SFF_DEBUG(DBG_ERROR, "param error, buf is NULL. sff_index: %u, cpld_reg_type: %d\n",
+ sff_index, cpld_reg_type);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ if (count <= 0) {
+ DFD_SFF_DEBUG(DBG_ERROR, "buf size error, count: %lu, sff index: %u, cpld_reg_type: %d\n",
+ count, sff_index, cpld_reg_type);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ mem_clear(buf, count);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_SFF_CPLD_REG, sff_index, cpld_reg_type);
+ ret = dfd_info_get_int(key, &value, NULL);
+ if (ret < 0) {
+ DFD_SFF_DEBUG(DBG_ERROR, "get sff%u cpld reg type %d error, key_name: %s, ret: %d\n",
+ sff_index, cpld_reg_type, key_to_name(DFD_CFG_ITEM_SFF_CPLD_REG), ret);
+ return ret;
+ }
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
+
+/**
+ * dfd_get_single_eth_optoe_type - get sff optoe type
+ * @sff_index: Optical module number, starting from 1
+ * @optoe_type: Optical module type
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+int dfd_get_single_eth_optoe_type(unsigned int sff_index, int *optoe_type)
+{
+ uint64_t key;
+ int ret, value;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_SFF_OPTOE_TYPE, sff_index, 0);
+ ret = dfd_info_get_int(key, &value, NULL);
+ if (ret < 0) {
+ DFD_SFF_DEBUG(DBG_ERROR, "get sff optoe type error, key_name: %s, ret:%d.\n",
+ key_to_name(DFD_CFG_ITEM_SFF_OPTOE_TYPE), ret);
+ return ret;
+ }
+
+ /* assic int to int */
+ *optoe_type = value - '0';
+ return ret;
+}
+
+/**
+ * dfd_set_single_eth_optoe_type - set sff optoe type
+ * @sff_index: Optical module number, starting from 1
+ * @optoe_type: Optical module type
+ * return: Success: Returns the length of fill buf
+ * : Failed: A negative value is returned
+ */
+int dfd_set_single_eth_optoe_type(unsigned int sff_index, int optoe_type)
+{
+ uint64_t key;
+ int ret, value;
+
+ /* int to assic int */
+ value = optoe_type + '0';
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_SFF_OPTOE_TYPE, sff_index, 0);
+ ret = dfd_info_set_int(key, value);
+ if (ret < 0) {
+ DFD_SFF_DEBUG(DBG_ERROR, "set sff optoe type error, key_name: %s, ret:%d.\n",
+ key_to_name(DFD_CFG_ITEM_SFF_OPTOE_TYPE), ret);
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_slot_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_slot_driver.c
new file mode 100644
index 000000000000..5ba743f3c4d4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_slot_driver.c
@@ -0,0 +1,174 @@
+/*
+ * An wb_slot_driver driver for slot devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_adapter.h"
+#include "dfd_cfg_info.h"
+#include "dfd_frueeprom.h"
+
+#define SLOT_SIZE (256)
+
+int g_dfd_slot_dbg_level = 0;
+module_param(g_dfd_slot_dbg_level, int, S_IRUGO | S_IWUSR);
+
+static char *dfd_get_slot_sysfs_name(void)
+{
+ uint64_t key;
+ char *sysfs_name;
+
+ /* string Type configuration item */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_SLOT_SYSFS_NAME, 0, 0);
+ sysfs_name = dfd_ko_cfg_get_item(key);
+ if (sysfs_name == NULL) {
+ DFD_SLOT_DEBUG(DBG_VERBOSE, "key_name=%s, sysfs_name is NULL, use default way.\n",
+ key_to_name(DFD_CFG_ITEM_SLOT_SYSFS_NAME));
+ } else {
+ DFD_SLOT_DEBUG(DBG_VERBOSE, "sysfs_name: %s.\n", sysfs_name);
+ }
+ return sysfs_name;
+}
+
+/**
+ * dfd_get_slot_status - Gets the subcard status
+ * @index: Number of the sub-card, starting from 1
+ * return: 0:ABSENT
+ * 1:OK
+ * : Negative value - Read failed
+ */
+static int dfd_get_slot_status(unsigned int slot_index)
+{
+ uint64_t key;
+ int ret;
+ int status;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_DEV_PRESENT_STATUS, WB_MAIN_DEV_SLOT, slot_index);
+ ret = dfd_info_get_int(key, &status, NULL);
+ if (ret < 0) {
+ DFD_SLOT_DEBUG(DBG_ERROR, "get slot status error, key_name:%s\n",
+ key_to_name(DFD_CFG_ITEM_DEV_PRESENT_STATUS));
+ return ret;
+ }
+ return status;
+}
+
+/**
+ * dfd_get_slot_status_str - Gets the subcard status
+ * @slot_index: Number of the sub-card, starting from 1
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Length of the status string
+ * : Negative value - Read failed
+ */
+ssize_t dfd_get_slot_status_str(unsigned int slot_index, char *buf, size_t count)
+{
+ int ret;
+ if (buf == NULL) {
+ DFD_SLOT_DEBUG(DBG_ERROR, "params error.slot_index:%d.",slot_index);
+ return -DFD_RV_INVALID_VALUE;
+ }
+ ret = dfd_get_slot_status(slot_index);
+ if (ret < 0) {
+ DFD_SLOT_DEBUG(DBG_ERROR, "get slot status error,ret:%d, slot_index:%d\n", ret, slot_index);
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", ret);
+}
+
+/**
+ * dfd_get_slot_info - Obtain the subcard information
+ * @slot_index: Number of the sub-card, starting from 1
+ * @cmd: Subcard information type, subcard name :2, subcard serial number :3, subcard hardware version number :5
+ * @buf: Receive buf
+ * @count: Accept the buf length
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_slot_info(unsigned int slot_index, uint8_t cmd, char *buf, size_t count)
+{
+ uint64_t key;
+ int rv;
+ char slot_buf[SLOT_SIZE];
+ dfd_i2c_dev_t *i2c_dev;
+ const char *sysfs_name;
+
+ if (buf == NULL) {
+ DFD_SLOT_DEBUG(DBG_ERROR, "buf is NULL, slot index:%d, cmd:%d\n", slot_index, cmd);
+ return -DFD_RV_INVALID_VALUE;
+ }
+
+ mem_clear(buf, count);
+ mem_clear(slot_buf, SLOT_SIZE);
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_OTHER_I2C_DEV, WB_MAIN_DEV_SLOT, slot_index);
+ i2c_dev = dfd_ko_cfg_get_item(key);
+ if (i2c_dev == NULL) {
+ DFD_SLOT_DEBUG(DBG_ERROR, "slot i2c dev config error, key_name=%s\n",
+ key_to_name(DFD_CFG_ITEM_OTHER_I2C_DEV));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ sysfs_name = dfd_get_slot_sysfs_name();
+ rv = dfd_get_fru_board_data(i2c_dev->bus, i2c_dev->addr, cmd, slot_buf, SLOT_SIZE, sysfs_name);
+
+ if (rv < 0) {
+ DFD_SLOT_DEBUG(DBG_ERROR, "slot eeprom read failed");
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ DFD_SLOT_DEBUG(DBG_VERBOSE, "%s\n", slot_buf);
+ snprintf(buf, count, "%s\n", slot_buf);
+ return strlen(buf);
+}
+
+ssize_t dfd_get_slot_power_status_str(unsigned int slot_index, char *buf, size_t count)
+{
+ uint64_t key;
+ int ret;
+ int status;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_POWER_STATUS, WB_MAIN_DEV_SLOT, slot_index);
+ ret = dfd_info_get_int(key, &status, NULL);
+ if (ret < 0) {
+ DFD_SLOT_DEBUG(DBG_ERROR, "get slot status error, key_name: %s\r\n",
+ key_to_name(DFD_CFG_ITEM_POWER_STATUS));
+ return ret;
+ }
+ mem_clear(buf, count);
+ return (ssize_t)snprintf(buf, count, "%d\n", status);
+}
+
+int dfd_set_slot_power_status_str(unsigned int slot_index, int value)
+{
+ uint64_t key;
+ int ret;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_POWER_STATUS, WB_MAIN_DEV_SLOT, slot_index);
+ ret = dfd_info_set_int(key, value);
+ if (ret < 0) {
+ DBG_SYSLED_DEBUG(DBG_ERROR, "set led status error, key_name: %s,ret:%d\r\n",
+ key_to_name(DFD_CFG_ITEM_POWER_STATUS), ret);
+ return ret;
+ }
+ return ret;
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_system_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_system_driver.c
new file mode 100644
index 000000000000..d938c118b086
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_system_driver.c
@@ -0,0 +1,253 @@
+/*
+ * An wb_system_driver driver for system devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_info.h"
+#include "dfd_cfg_adapter.h"
+#include "wb_system_driver.h"
+#include "switch_driver.h"
+
+#define NODE_MAX_LEN (64)
+
+int g_dfd_custom_dbg_level = 0;
+module_param(g_dfd_custom_dbg_level, int, S_IRUGO | S_IWUSR);
+
+/* Get current function step number */
+int dfd_get_cmd_count(unsigned int type)
+{
+ uint64_t key;
+ int cmd_num;
+ int *p_cmd_num;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_BMC_SYSTEM_CMD_NUM, type, 0);
+ p_cmd_num = dfd_ko_cfg_get_item(key);
+ if (p_cmd_num == NULL) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "get cmd number failed, key_name:%s\n",
+ key_to_name(DFD_CFG_ITEM_BMC_SYSTEM_CMD_NUM));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ cmd_num = *p_cmd_num;
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "get cmd number ok, type:0x%x, number:%d\n", type, cmd_num);
+ return cmd_num;
+}
+
+void dfd_cmd_delay(unsigned int usdelay)
+{
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "usdelay:%d\n", usdelay);
+ usleep_range(usdelay, usdelay + 1);
+ return;
+}
+
+ssize_t dfd_system_get_system_value(unsigned int type, int *value)
+{
+ uint64_t key;
+ int ret;
+ info_ctrl_t *info_ctrl;
+ int *p_decode_value;
+
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_BMC_SYSTEM, type, 0);
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "get info ctrl fail, key_name: %s, type=0x%x\n",
+ key_to_name(DFD_CFG_ITEM_BMC_SYSTEM), type);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "get, key_name: %s, type=0x%x\n",
+ key_to_name(DFD_CFG_ITEM_BMC_SYSTEM), type);
+ ret = dfd_info_get_int(key, value, NULL);
+ if (ret < 0) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "get system value error, key_name: %s, type=0x%x, ret:%d\n",
+ key_to_name(DFD_CFG_ITEM_BMC_SYSTEM), type, ret);
+ return ret;
+ }
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_SYSTEM_STATUS_DECODE, type, *value);
+ p_decode_value = dfd_ko_cfg_get_item(key);
+ if (p_decode_value == NULL) {
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "type:%d, status needn't decode. value:0x%x\n", type, *value);
+ } else {
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "type:%d, ori_value:0x%x, decoded value:0x%x\n", type, *value, *p_decode_value);
+ *value = *p_decode_value;
+ }
+ return DFD_RV_OK;
+}
+
+static int dfd_system_check_value_i(unsigned int type_detail, int cmd_i)
+{
+ uint64_t key;
+ int ret, i;
+ info_ctrl_t *info_ctrl;
+ int tmp_value, retry_times;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM, type_detail, cmd_i);
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "key=%s, type_detail=0x%x, cmd_i=%d, don't need to check value\n",
+ key_to_name(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM), type_detail, cmd_i);
+ return DFD_RV_OK;
+ }
+
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "key_name=%s, type_detail=0x%x, cmd_i=%d, start to check value,\n",
+ key_to_name(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM), type_detail, cmd_i);
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "check value, except value: %d, retry_times: %d, sleep_time: %dus\n",
+ info_ctrl->int_extra1, info_ctrl->int_extra2, info_ctrl->int_extra3);
+
+ if (info_ctrl->int_extra2 <= 0) {
+ retry_times = 1;
+ } else {
+ retry_times = info_ctrl->int_extra2;
+ }
+
+ for (i = 0; i < retry_times; i++) {
+ ret = dfd_info_get_int(key, &tmp_value, NULL);
+ if (ret < 0) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "key_name=%s, type_detail=0x%x, cmd_i=%d, get check value error, ret: %d\n",
+ key_to_name(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM), type_detail, cmd_i, ret);
+ return ret;
+ }
+ if (tmp_value == info_ctrl->int_extra1) {
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "key_name=%s, type_detail=0x%x, cmd_i=%d, check value ok, get value: %d, except value: %d\n",
+ key_to_name(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM), type_detail, cmd_i, tmp_value, info_ctrl->int_extra1);
+ return DFD_RV_OK;
+ }
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "key_name=%s, type_detail=0x%x, cmd_i=%d, check value failed, get value: %d, except value: %d, retry: %d\n",
+ key_to_name(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM), type_detail, cmd_i, tmp_value, info_ctrl->int_extra1, i + 1);
+
+ if (info_ctrl->int_extra3 > 0) {
+ dfd_cmd_delay(info_ctrl->int_extra3);
+ }
+ }
+
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "key_name=%s, type_detail=0x%x, cmd_i=%d, check value failed, get value: %d, except value: %d\n",
+ key_to_name(DFD_CFG_ITEM_CHECK_VAL_BMC_SYSTEM), type_detail, cmd_i, tmp_value, info_ctrl->int_extra1);
+ return -DFD_RV_CHECK_FAIL;
+}
+
+ssize_t dfd_system_set_system_value(unsigned int type, int value)
+{
+ uint64_t key;
+ int ret, cmd_i, cmd_count;
+ info_ctrl_t *info_ctrl;
+ unsigned int type_detail;
+ int tmp_value;
+
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "set system value, type=0x%x, value=%d\n", type, value);
+ /* get step number */
+ type_detail = type | (value & 0xff);
+ ret = dfd_get_cmd_count(type_detail);
+ if(ret <= 0) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "get cmd number, type_detail=0x%x\n", type_detail);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ cmd_count = ret;
+ /* exec each step */
+ for(cmd_i = 0; cmd_i < cmd_count; cmd_i++) {
+ /* first do pre check */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_PRE_CHECK_BMC_SYSTEM, type_detail, cmd_i);
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl) {
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "key_name=%s, type_detail=0x%x, cmd_i=%d, start to pre check\n",
+ key_to_name(DFD_CFG_ITEM_PRE_CHECK_BMC_SYSTEM), type_detail, cmd_i);
+ ret = dfd_info_get_int(key, &tmp_value, NULL);
+ if (ret < 0) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "key_name=%s, type_detail=0x%x, cmd_i=%d, get pre check value error, ret: %d\n",
+ key_to_name(DFD_CFG_ITEM_PRE_CHECK_BMC_SYSTEM), type_detail, cmd_i, ret);
+ return ret;
+ }
+ if (tmp_value != info_ctrl->int_extra1) {
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "key_name=%s, type_detail=0x%x, cmd_i=%d, pre check error, get value: %d, except value: %d, skip this step\n",
+ key_to_name(DFD_CFG_ITEM_PRE_CHECK_BMC_SYSTEM), type_detail, cmd_i, tmp_value, info_ctrl->int_extra1);
+ continue;
+ }
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "key_name=%s, type_detail=0x%x, cmd_i=%d, pre check ok, get value: %d, except value: %d\n",
+ key_to_name(DFD_CFG_ITEM_PRE_CHECK_BMC_SYSTEM), type_detail, cmd_i, tmp_value, info_ctrl->int_extra1);
+ }
+ /* get current step cfg */
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_BMC_SYSTEM, type_detail, cmd_i);
+ info_ctrl = dfd_ko_cfg_get_item(key);
+ if (info_ctrl == NULL) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "get info ctrl fail, key_name=%s, type_detail=0x%x, cmd_i=%d\n",
+ key_to_name(DFD_CFG_ITEM_BMC_SYSTEM), type_detail, cmd_i);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DFD_SYSTEM_DEBUG(DBG_VERBOSE, "set, key_name=%s, type_detail=0x%x, cmd_i=%d\n",
+ key_to_name(DFD_CFG_ITEM_BMC_SYSTEM), type_detail, cmd_i);
+ /* set int type info */
+ ret = dfd_info_set_int(key, info_ctrl->int_cons);
+ if (ret < 0) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "set system value error, key_name=%s, type_detail=0x%x, cmd_i=%d, value=%d, ret:%d\n",
+ key_to_name(DFD_CFG_ITEM_BMC_SYSTEM), type_detail, cmd_i, value, ret);
+ return ret;
+ }
+
+ /* delay if it has */
+ if(info_ctrl->int_extra1 > 0) {
+ dfd_cmd_delay(info_ctrl->int_extra1);
+ }
+
+ /* check value */
+ ret = dfd_system_check_value_i(type_detail, cmd_i);
+ if (ret < 0) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "set system value check value error, ret: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return DFD_RV_OK;
+}
+
+ssize_t dfd_system_get_port_power_status(unsigned int type, char *buf, size_t count)
+{
+ int ret, cmd_i, cmd_count;
+ unsigned int type_detail;
+
+ /* get step number */
+ type_detail = type;
+ ret = dfd_get_cmd_count(type_detail);
+ if(ret <= 0) {
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "get cmd number, type_detail=0x%x\n", type_detail);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ cmd_count = ret;
+ /* exec each step */
+ for(cmd_i = 0; cmd_i < cmd_count; cmd_i++) {
+ /* check value */
+ ret = dfd_system_check_value_i(type_detail, cmd_i);
+ if (ret < 0) {
+ if(ret == -DFD_RV_CHECK_FAIL) {
+ return (ssize_t)snprintf(buf, count, "%d\n", WB_PORT_POWER_ON);
+ }
+ DFD_SYSTEM_DEBUG(DBG_ERROR, "set system value check value error, ret: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return (ssize_t)snprintf(buf, count, "%d\n", WB_PORT_POWER_OFF);
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_watchdog_driver.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_watchdog_driver.c
new file mode 100644
index 000000000000..a146b2e9a337
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/switch_driver/wb_watchdog_driver.c
@@ -0,0 +1,217 @@
+/*
+ * An wb_watchdog_driver driver for watchdog devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+
+#include "wb_module.h"
+#include "dfd_cfg.h"
+#include "dfd_cfg_info.h"
+#include "dfd_cfg_adapter.h"
+
+#define WDT_FILE_NAME_LEN (64)
+#define WDT_ABSOLUTE_PATH_NAME_LEN (256)
+#define WDT_SYSFS_FILE_DIR ("/sys/class/watchdog/watchdog%d/")
+
+typedef enum wb_wdt_enable_status_e {
+ WB_WDT_DISENABLE = 0, /* close watchdog */
+ WB_WDT_ENABLE = 1, /* open watchdog */
+} wb_wdt_enable_status_t;
+
+struct wdt_file_enable_status_s {
+ wb_wdt_enable_status_t value;
+ char state[WDT_FILE_NAME_LEN];
+};
+
+struct wdt_file_enable_status_s wdt_file_enable_status_match[] = {
+ {WB_WDT_DISENABLE, "inactive"},
+ {WB_WDT_ENABLE, "active"},
+};
+
+int g_dfd_watchdog_dbg_level = 0;
+module_param(g_dfd_watchdog_dbg_level, int, S_IRUGO | S_IWUSR);
+
+static int watchdog_file_read(char *fpath, char *buf, int size)
+{
+ int ret;
+ struct file *filp;
+ loff_t pos;
+
+ filp = filp_open(fpath, O_RDONLY, 0);
+ if (IS_ERR(filp)) {
+ DFD_WDT_DEBUG(DBG_ERROR, "watchdog can't open %s.\n", fpath);
+ filp = NULL;
+ ret = -ENOENT;
+ return ret;
+ }
+
+ mem_clear(buf, size);
+ pos = 0;
+ ret = kernel_read(filp, buf, size - 1, &pos);
+ if (ret < 0) {
+ DFD_WDT_DEBUG(DBG_ERROR, "kernel_read failed, path=%s, addr=0, size=%d, ret=%d\n",
+ fpath, size -1, ret);
+ }
+
+ filp_close(filp, NULL);
+ filp = NULL;
+ return ret;
+}
+
+/**
+ * dfd_get_watchdog_id - Obtain watchdog Number
+ * @wdt_index: watchdwatchdog index number
+
+ * return: Succeeded: The watchdog number is returned
+ * : Failed: A negative value is returned
+ */
+static int dfd_get_watchdog_id(unsigned int wdt_index)
+{
+ uint64_t key;
+ int *p_watchdog_id;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_WATCHDOG_ID, wdt_index, 0);
+ p_watchdog_id = dfd_ko_cfg_get_item(key);
+ if (p_watchdog_id == NULL) {
+ DFD_WDT_DEBUG(DBG_ERROR, "get watchdog id error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_WATCHDOG_ID));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+ DFD_WDT_DEBUG(DBG_VERBOSE, "get watchdog id ok, watchdog index:%u, id:0x%x.\n",
+ wdt_index, *p_watchdog_id);
+ return *p_watchdog_id;
+}
+
+static int watchdog_get_file_name(unsigned int wdt_index, wb_wdt_type_t type, char *buf, int len)
+{
+ uint64_t key;
+ char *watchdog_name;
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_WATCHDOG_NAME, wdt_index, type);
+ watchdog_name = dfd_ko_cfg_get_item(key);
+ if (watchdog_name == NULL) {
+ DFD_WDT_DEBUG(DBG_ERROR, "watchdog name config error, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_WATCHDOG_NAME));
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ DFD_WDT_DEBUG(DBG_VERBOSE, "get watchdog%u %s\n", wdt_index, watchdog_name);
+ snprintf(buf, len, "%s", watchdog_name);
+ return DFD_RV_OK;
+}
+
+/**
+ * dfd_get_watchdog_info - Get watchdog information
+ * @type: Watchdog information type
+ * @buf: Receive buf
+ * return: Success: Returns the length of buf
+ * : Failed: A negative value is returned
+ */
+ssize_t dfd_get_watchdog_info(uint8_t type, char *buf, size_t count)
+{
+ char fpath[WDT_ABSOLUTE_PATH_NAME_LEN];
+ int watchdog_id, len, ret;
+
+ /* get watchdog sysfs name */
+ watchdog_id = dfd_get_watchdog_id(0);
+ mem_clear(fpath, WDT_ABSOLUTE_PATH_NAME_LEN);
+ snprintf(fpath, WDT_ABSOLUTE_PATH_NAME_LEN - 1, WDT_SYSFS_FILE_DIR, watchdog_id);
+ len = strlen(fpath);
+ ret = watchdog_get_file_name(watchdog_id, type, &fpath[len], WDT_ABSOLUTE_PATH_NAME_LEN - len);
+ if (ret < 0) {
+ DFD_WDT_DEBUG(DBG_WARN, "watchdog type[%u] don't support to get sysfs name.\n", type);
+ return -DFD_RV_DEV_NOTSUPPORT;
+ }
+
+ ret = watchdog_file_read(fpath, buf, count - 1);
+ if (ret < 0) {
+ DFD_WDT_DEBUG(DBG_ERROR, "watchdog read file %s error, ret: %d\n", fpath, ret);
+ }
+
+ return ret;
+}
+
+ssize_t dfd_watchdog_get_status(char *buf, size_t count)
+{
+ uint64_t key;
+ int watchdog_id, ret, value;
+
+ watchdog_id = dfd_get_watchdog_id(0);
+
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_WATCHDOG_DEV, watchdog_id, WB_WDT_TYPE_ENABLE);
+ ret = dfd_info_get_int(key, &value, NULL);
+ if (ret < 0) {
+ DFD_WDT_DEBUG(DBG_ERROR, "get watchdog enable status, key_name: %s\n",
+ key_to_name(DFD_CFG_ITEM_WATCHDOG_DEV));
+ return ret;
+ }
+ DFD_WDT_DEBUG(DBG_VERBOSE, "get watchdog enable status ok, watchdog index:%u, enable:0x%x.\n",
+ watchdog_id, value);
+ return (ssize_t)snprintf(buf, count, "%d\n", value);
+}
+
+ssize_t dfd_watchdog_set_status(int value)
+{
+ uint64_t key;
+ int watchdog_id, ret;
+
+ watchdog_id = dfd_get_watchdog_id(0);
+ key = DFD_CFG_KEY(DFD_CFG_ITEM_WATCHDOG_DEV, watchdog_id, WB_WDT_TYPE_ENABLE);
+ ret = dfd_info_set_int(key, value);
+ if (ret < 0) {
+ DFD_WDT_DEBUG(DBG_ERROR, "set watchdog enable status, key: %s\n",
+ key_to_name(DFD_CFG_ITEM_WATCHDOG_DEV));
+ return ret;
+ }
+ DFD_WDT_DEBUG(DBG_VERBOSE, "set watchdog enable status ok, watchdog index:%u, enable:0x%x.\n",
+ watchdog_id, value);
+ return 0;
+}
+
+ssize_t dfd_watchdog_get_status_str(char *buf, size_t count)
+{
+ int ret, i;
+ int enable_status;
+
+ ret = dfd_get_watchdog_info(WB_WDT_TYPE_STATE, buf, count);
+ if (ret < 0) {
+ DFD_WDT_DEBUG(DBG_ERROR, "watchdog type[%d] get sysfs name failed.\n", WB_WDT_TYPE_STATE);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ enable_status = -1;
+ for (i = 0; i < ARRAY_SIZE(wdt_file_enable_status_match); i++) {
+ if (strncmp(wdt_file_enable_status_match[i].state, buf, \
+ strlen(wdt_file_enable_status_match[i].state)) == 0) {
+ enable_status = wdt_file_enable_status_match[i].value;
+ DFD_WDT_DEBUG(DBG_VERBOSE, "watchdog read state file %s match enable status[%d].\n",
+ buf, enable_status);
+ break;
+ }
+ }
+
+ if (enable_status < 0) {
+ DFD_WDT_DEBUG(DBG_ERROR, "watchdog read state file %s don't match enable status\n", buf);
+ return -DFD_RV_DEV_FAIL;
+ }
+
+ return (ssize_t)snprintf(buf, count, "%d\n", enable_status);
+}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/Makefile b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/Makefile
new file mode 100644
index 000000000000..197a0e6ff98f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/Makefile
@@ -0,0 +1,34 @@
+PWD = $(shell pwd)
+
+MAKEFILE_FILE_PATH = $(abspath $(lastword $(MAKEFILE_LIST)))
+DEV_SYSFS_HEADER_DIR = $(abspath $(MAKEFILE_FILE_PATH)/../../sysfs_driver/include)
+SWITCH_DVR_HEADER_DIR = $(abspath $(MAKEFILE_FILE_PATH)/../../switch_driver/include)
+EXTRA_CFLAGS:= -I$(M)/include
+EXTRA_CFLAGS+= -I$(DEV_SYSFS_HEADER_DIR)
+EXTRA_CFLAGS+= -I$(SWITCH_DVR_HEADER_DIR)
+EXTRA_CFLAGS+= -Wall
+
+s3ip_sysfs-objs := switch.o cpld_sysfs.o \
+curr_sensor_sysfs.o \
+fan_sysfs.o \
+fpga_sysfs.o \
+psu_sysfs.o \
+slot_sysfs.o \
+sysled_sysfs.o \
+temp_sensor_sysfs.o \
+transceiver_sysfs.o \
+vol_sensor_sysfs.o \
+watchdog_sysfs.o \
+system_sysfs.o \
+eeprom_sysfs.o \
+
+obj-m := s3ip_sysfs.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
+ rm -f $(PWD)/Module.markers $(PWD)/Module.symvers $(PWD)/modules.order
+ rm -rf $(PWD)/.tmp_versions
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/cpld_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/cpld_sysfs.c
new file mode 100644
index 000000000000..d5b13e3a83f5
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/cpld_sysfs.c
@@ -0,0 +1,444 @@
+/*
+ * An cpld_sysfs driver for cpld sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+
+#include "switch.h"
+#include "cpld_sysfs.h"
+
+static int g_cpld_loglevel = 0;
+
+#define CPLD_REBOOT_CAUSE_FILE "/etc/.reboot/.previous-reboot-cause.txt"
+#define REBOOT_CAUSE_NAME_LEN (64)
+
+/* Reboot cause type */
+typedef enum wb_reboot_cause_type_e {
+ REBOOT_CAUSE_NON_HARDWARE = 0,
+ REBOOT_CAUSE_POWER_LOSS,
+ REBOOT_CAUSE_THERMAL_OVERLOAD_CPU,
+ REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC,
+ REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER,
+ REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED,
+ REBOOT_CAUSE_WATCHDOG,
+ REBOOT_CAUSE_HARDWARE_OTHER,
+ REBOOT_CAUSE_CPU_COLD_RESET,
+ REBOOT_CAUSE_CPU_WARM_RESET,
+ REBOOT_CAUSE_BIOS_RESET,
+ REBOOT_CAUSE_PSU_SHUTDOWN,
+ REBOOT_CAUSE_BMC_SHUTDOWN,
+ REBOOT_CAUSE_RESET_BUTTON_SHUTDOWN,
+ REBOOT_CAUSE_RESET_BUTTON_COLD_SHUTDOWN,
+} wb_reboot_cause_type_t;
+
+struct reboot_cause_file_info_s {
+ wb_reboot_cause_type_t reboot_cause_type;
+ char reboot_cause_name[REBOOT_CAUSE_NAME_LEN];
+};
+
+struct reboot_cause_file_info_s reboot_cause_file_info_match[] = {
+ {REBOOT_CAUSE_POWER_LOSS, "Power Loss"},
+ {REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, "Watchdog reboot"},
+ {REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER, "BMC reboot"},
+ {REBOOT_CAUSE_BMC_SHUTDOWN, "BMC powerdown"},
+ {REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, "Thermal Overload: ASIC"},
+ {REBOOT_CAUSE_CPU_WARM_RESET, "Warm reboot"},
+};
+
+#define CPLD_INFO(fmt, args...) do { \
+ if (g_cpld_loglevel & INFO) { \
+ printk(KERN_INFO "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define CPLD_ERR(fmt, args...) do { \
+ if (g_cpld_loglevel & ERR) { \
+ printk(KERN_ERR "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define CPLD_DBG(fmt, args...) do { \
+ if (g_cpld_loglevel & DBG) { \
+ printk(KERN_DEBUG "[CPLD_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct cpld_obj_s {
+ struct switch_obj *obj;
+};
+
+struct cpld_s {
+ unsigned int cpld_number;
+ struct cpld_obj_s *cpld;
+};
+
+static struct cpld_s g_cpld;
+static struct switch_obj *g_cpld_obj = NULL;
+static struct s3ip_sysfs_cpld_drivers_s *g_cpld_drv = NULL;
+
+static int cpld_file_read(char *fpath, char *buf, int size)
+{
+ int ret;
+ struct file *filp;
+ loff_t pos;
+
+ filp = filp_open(fpath, O_RDONLY, 0);
+ if (IS_ERR(filp)) {
+ CPLD_ERR("can't open %s", fpath);
+ filp = NULL;
+ ret = -ENOENT;
+ goto fail;
+ }
+ mem_clear(buf, size);
+ pos = 0;
+ ret = kernel_read(filp, buf, size - 1, &pos);
+ if (ret < 0) {
+ CPLD_ERR("read file %s error, ret:%d\n", fpath, ret);
+ }
+fail:
+ if (filp != NULL) {
+ filp_close(filp, NULL);
+ filp = NULL;
+ }
+
+ return ret;
+}
+
+static ssize_t cpld_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_cpld.cpld_number);
+}
+
+static ssize_t cpld_reboot_cause_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ char reboot_cause_buf[REBOOT_CAUSE_NAME_LEN];
+ int ret, i;
+ char *point;
+ int reboot_cause_type;
+
+ mem_clear(reboot_cause_buf, sizeof(reboot_cause_buf));
+ ret = cpld_file_read(CPLD_REBOOT_CAUSE_FILE, reboot_cause_buf, REBOOT_CAUSE_NAME_LEN - 1);
+ if (ret < 0) {
+ CPLD_ERR("read file %s error, ret:%d\n", CPLD_REBOOT_CAUSE_FILE, ret);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 0);
+ }
+
+ point = strchr(reboot_cause_buf, ',');
+ if (point != NULL) {
+ *point = 0;
+ }
+ CPLD_DBG("read reboot cause:%s\n", reboot_cause_buf);
+
+ reboot_cause_type = 0;
+ for (i = 0; i < ARRAY_SIZE(reboot_cause_file_info_match); i++) {
+ if (strncmp(reboot_cause_file_info_match[i].reboot_cause_name, reboot_cause_buf, \
+ strlen(reboot_cause_file_info_match[i].reboot_cause_name)) == 0) {
+ reboot_cause_type = reboot_cause_file_info_match[i].reboot_cause_type;
+ CPLD_DBG("reboot cause %s match type[%d].\n", reboot_cause_file_info_match[i].reboot_cause_name, reboot_cause_type);
+ break;
+ }
+ }
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", reboot_cause_type);
+}
+
+static ssize_t cpld_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int cpld_index;
+
+ check_p(g_cpld_drv);
+ check_p(g_cpld_drv->get_main_board_cpld_alias);
+
+ cpld_index = obj->index;
+ CPLD_DBG("cpld index: %u\n", cpld_index);
+ return g_cpld_drv->get_main_board_cpld_alias(cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t cpld_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int cpld_index;
+
+ check_p(g_cpld_drv);
+ check_p(g_cpld_drv->get_main_board_cpld_type);
+
+ cpld_index = obj->index;
+ CPLD_DBG("cpld index: %u\n", cpld_index);
+ return g_cpld_drv->get_main_board_cpld_type(cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t cpld_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int cpld_index;
+
+ check_p(g_cpld_drv);
+ check_p(g_cpld_drv->get_main_board_cpld_firmware_version);
+
+ cpld_index = obj->index;
+ CPLD_DBG("cpld index: %u\n", cpld_index);
+ return g_cpld_drv->get_main_board_cpld_firmware_version(cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t cpld_board_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int cpld_index;
+
+ check_p(g_cpld_drv);
+ check_p(g_cpld_drv->get_main_board_cpld_board_version);
+
+ cpld_index = obj->index;
+ CPLD_DBG("cpld index: %u\n", cpld_index);
+ return g_cpld_drv->get_main_board_cpld_board_version(cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t cpld_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int cpld_index;
+
+ check_p(g_cpld_drv);
+ check_p(g_cpld_drv->get_main_board_cpld_test_reg);
+
+ cpld_index = obj->index;
+ CPLD_DBG("cpld index: %u\n", cpld_index);
+ return g_cpld_drv->get_main_board_cpld_test_reg(cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t cpld_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int cpld_index, value;
+ int ret;
+
+ check_p(g_cpld_drv);
+ check_p(g_cpld_drv->set_main_board_cpld_test_reg);
+
+ cpld_index = obj->index;
+ sscanf(buf, "0x%x", &value);
+ ret = g_cpld_drv->set_main_board_cpld_test_reg(cpld_index, value);
+ if (ret < 0) {
+ CPLD_ERR("set cpld%u test reg failed, value:0x%x, ret: %d.\n", cpld_index, value, ret);
+ return ret;
+ }
+ CPLD_DBG("set cpld%u test reg success, value: 0x%x.\n", cpld_index, value);
+ return count;
+}
+
+/************************************cpld dir and attrs*******************************************/
+static struct switch_attribute cpld_number_att = __ATTR(number, S_IRUGO, cpld_number_show, NULL);
+static struct switch_attribute cpld_reboot_cause_att = __ATTR(reboot_cause, S_IRUGO, cpld_reboot_cause_show, NULL);
+
+static struct attribute *cpld_dir_attrs[] = {
+ &cpld_number_att.attr,
+ &cpld_reboot_cause_att.attr,
+ NULL,
+};
+
+static struct attribute_group cpld_root_attr_group = {
+ .attrs = cpld_dir_attrs,
+};
+
+/*******************************cpld[1-n] dir and attrs*******************************************/
+static struct switch_attribute cpld_alias_attr = __ATTR(alias, S_IRUGO, cpld_alias_show, NULL);
+static struct switch_attribute cpld_type_attr = __ATTR(type, S_IRUGO, cpld_type_show, NULL);
+static struct switch_attribute cpld_fw_version_attr = __ATTR(firmware_version, S_IRUGO, cpld_fw_version_show, NULL);
+static struct switch_attribute cpld_board_version_attr = __ATTR(board_version, S_IRUGO, cpld_board_version_show, NULL);
+static struct switch_attribute cpld_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, cpld_test_reg_show, cpld_test_reg_store);
+
+static struct attribute *cpld_attrs[] = {
+ &cpld_alias_attr.attr,
+ &cpld_type_attr.attr,
+ &cpld_fw_version_attr.attr,
+ &cpld_board_version_attr.attr,
+ &cpld_test_reg_attr.attr,
+ NULL,
+};
+
+static struct attribute_group cpld_attr_group = {
+ .attrs = cpld_attrs,
+};
+
+static int cpld_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct cpld_obj_s *curr_cpld;
+
+ curr_cpld = &g_cpld.cpld[index - 1];
+ if (curr_cpld->obj) {
+ sysfs_remove_group(&curr_cpld->obj->kobj, &cpld_attr_group);
+ switch_kobject_delete(&curr_cpld->obj);
+ CPLD_DBG("delete cpld%u dir and attrs success.\n", index);
+ }
+
+ return 0;
+}
+
+static int cpld_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ char name[8];
+ struct cpld_obj_s *curr_cpld;
+
+ curr_cpld = &g_cpld.cpld[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "cpld%u", index);
+ curr_cpld->obj = switch_kobject_create(name, parent);
+ if (!curr_cpld->obj) {
+ CPLD_ERR("create %s object error!\n", name);
+ return -EBADRQC;
+ }
+ curr_cpld->obj->index = index;
+ if (sysfs_create_group(&curr_cpld->obj->kobj, &cpld_attr_group) != 0) {
+ CPLD_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&curr_cpld->obj);
+ return -EBADRQC;
+ }
+ CPLD_DBG("create %s dir and attrs success.\n", name);
+ return 0;
+}
+
+static int cpld_sub_create_kobj_and_attrs(struct kobject *parent, int cpld_num)
+{
+ unsigned int cpld_index, i;
+
+ g_cpld.cpld = kzalloc(sizeof(struct cpld_obj_s) * cpld_num, GFP_KERNEL);
+ if (!g_cpld.cpld) {
+ CPLD_ERR("kzalloc g_cpld.cpld error, cpld number = %d.\n", cpld_num);
+ return -ENOMEM;
+ }
+
+ for (cpld_index = 1; cpld_index <= cpld_num; cpld_index++) {
+ if (cpld_sub_single_create_kobj_and_attrs(parent, cpld_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = cpld_index; i > 0; i--) {
+ cpld_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_cpld.cpld);
+ g_cpld.cpld = NULL;
+ return -EBADRQC;
+}
+
+/* create cpld[1-n] directory and attributes*/
+static int cpld_sub_create(void)
+{
+ int ret;
+
+ ret = cpld_sub_create_kobj_and_attrs(&g_cpld_obj->kobj, g_cpld.cpld_number);
+ return ret;
+}
+
+/* delete cpld[1-n] directory and attributes*/
+static void cpld_sub_remove(void)
+{
+ unsigned int cpld_index;
+
+ if (g_cpld.cpld) {
+ for (cpld_index = g_cpld.cpld_number; cpld_index > 0; cpld_index--) {
+ cpld_sub_single_remove_kobj_and_attrs(cpld_index);
+ }
+ kfree(g_cpld.cpld);
+ g_cpld.cpld = NULL;
+ }
+ g_cpld.cpld_number = 0;
+ return;
+}
+
+/* create cpld directory and number attributes */
+static int cpld_root_create(void)
+{
+ g_cpld_obj = switch_kobject_create("cpld", NULL);
+ if (!g_cpld_obj) {
+ CPLD_ERR("switch_kobject_create cpld error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_cpld_obj->kobj, &cpld_root_attr_group) != 0) {
+ switch_kobject_delete(&g_cpld_obj);
+ CPLD_ERR("create cpld dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete cpld directory and number attributes */
+static void cpld_root_remove(void)
+{
+ if (g_cpld_obj) {
+ sysfs_remove_group(&g_cpld_obj->kobj, &cpld_root_attr_group);
+ switch_kobject_delete(&g_cpld_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_cpld_drivers_register(struct s3ip_sysfs_cpld_drivers_s *drv)
+{
+ int ret, cpld_num;
+
+ CPLD_INFO("s3ip_sysfs_cpld_drivers_register...\n");
+ if (g_cpld_drv) {
+ CPLD_ERR("g_cpld_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_main_board_cpld_number);
+ g_cpld_drv = drv;
+
+ cpld_num = g_cpld_drv->get_main_board_cpld_number();
+ if (cpld_num <= 0) {
+ CPLD_ERR("cpld number: %d, don't need to create cpld dirs and attrs.\n", cpld_num);
+ g_cpld_drv = NULL;
+ return -EINVAL;
+ }
+
+ mem_clear(&g_cpld, sizeof(struct cpld_s));
+ g_cpld.cpld_number = cpld_num;
+ ret = cpld_root_create();
+ if (ret < 0) {
+ CPLD_ERR("create cpld root dir and attrs failed, ret: %d\n", ret);
+ g_cpld_drv = NULL;
+ return ret;
+ }
+ ret = cpld_sub_create();
+ if (ret < 0) {
+ CPLD_ERR("create cpld sub dir and attrs failed, ret: %d\n", ret);
+ cpld_root_remove();
+ g_cpld_drv = NULL;
+ return ret;
+ }
+ CPLD_INFO("s3ip_sysfs_cpld_drivers_register success\n");
+ return 0;
+}
+
+void s3ip_sysfs_cpld_drivers_unregister(void)
+{
+ if (g_cpld_drv) {
+ cpld_sub_remove();
+ cpld_root_remove();
+ g_cpld_drv = NULL;
+ CPLD_DBG("s3ip_sysfs_cpld_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_cpld_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_cpld_drivers_unregister);
+module_param(g_cpld_loglevel, int, 0644);
+MODULE_PARM_DESC(g_cpld_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/curr_sensor_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/curr_sensor_sysfs.c
new file mode 100644
index 000000000000..3d2e86382ef1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/curr_sensor_sysfs.c
@@ -0,0 +1,385 @@
+/*
+ * An curr_sensor_sysfs driver for current sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "curr_sensor_sysfs.h"
+
+static int g_curr_sensor_loglevel = 0;
+
+#define CURR_SENSOR_INFO(fmt, args...) do { \
+ if (g_curr_sensor_loglevel & INFO) { \
+ printk(KERN_INFO "[CURR_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define CURR_SENSOR_ERR(fmt, args...) do { \
+ if (g_curr_sensor_loglevel & ERR) { \
+ printk(KERN_ERR "[CURR_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define CURR_SENSOR_DBG(fmt, args...) do { \
+ if (g_curr_sensor_loglevel & DBG) { \
+ printk(KERN_DEBUG "[CURR_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct curr_sensor_obj_s {
+ struct switch_obj *obj;
+};
+
+struct curr_sensor_s {
+ unsigned int curr_number;
+ struct curr_sensor_obj_s *curr;
+};
+
+static struct s3ip_sysfs_curr_sensor_drivers_s *g_curr_sensor_drv = NULL;
+static struct curr_sensor_s g_curr_sensor;
+static struct switch_obj *g_curr_sensor_obj = NULL;
+
+static ssize_t curr_sensor_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_curr_sensor.curr_number);
+}
+
+static ssize_t curr_sensor_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int curr_index;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->get_main_board_curr_value);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ return g_curr_sensor_drv->get_main_board_curr_value(curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t curr_sensor_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int curr_index;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->get_main_board_curr_alias);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ return g_curr_sensor_drv->get_main_board_curr_alias(curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t curr_sensor_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int curr_index;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->get_main_board_curr_type);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ return g_curr_sensor_drv->get_main_board_curr_type(curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t curr_sensor_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int curr_index;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->get_main_board_curr_max);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ return g_curr_sensor_drv->get_main_board_curr_max(curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t curr_sensor_max_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int curr_index;
+ int ret;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->set_main_board_curr_max);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ ret = g_curr_sensor_drv->set_main_board_curr_max(curr_index, buf, count);
+ if (ret < 0) {
+ CURR_SENSOR_ERR("set curr%u max threshold failed, value: %s, count: %lu, ret: %d\n",
+ curr_index, buf, count, ret);
+ return ret;
+ }
+ CURR_SENSOR_DBG("set curr%u max threshold success, value: %s, count: %lu, ret: %d\n",
+ curr_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t curr_sensor_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int curr_index;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->get_main_board_curr_min);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ return g_curr_sensor_drv->get_main_board_curr_min(curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t curr_sensor_min_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int curr_index;
+ int ret;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->set_main_board_curr_min);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ ret = g_curr_sensor_drv->set_main_board_curr_min(curr_index, buf, count);
+ if (ret < 0) {
+ CURR_SENSOR_ERR("set curr%u min threshold failed, value: %s, count: %lu, ret: %d\n",
+ curr_index, buf, count, ret);
+ return ret;
+ }
+ CURR_SENSOR_DBG("set curr%u min threshold success, value: %s, count: %lu, ret: %d\n",
+ curr_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t curr_sensor_monitor_flag_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int curr_index;
+
+ check_p(g_curr_sensor_drv);
+ check_p(g_curr_sensor_drv->get_main_board_curr_monitor_flag);
+
+ curr_index = obj->index;
+ CURR_SENSOR_DBG("curr index: %u\n", curr_index);
+ return g_curr_sensor_drv->get_main_board_curr_monitor_flag(curr_index, buf, PAGE_SIZE);
+}
+/************************************curr_sensor dir and attrs*******************************************/
+static struct switch_attribute num_curr_att = __ATTR(number, S_IRUGO, curr_sensor_number_show, NULL);
+
+static struct attribute *curr_sensor_dir_attrs[] = {
+ &num_curr_att.attr,
+ NULL,
+};
+
+static struct attribute_group curr_sensor_root_attr_group = {
+ .attrs = curr_sensor_dir_attrs,
+};
+
+/*******************************curr1 curr2 dir and attrs*******************************************/
+static struct switch_attribute curr_value_attr = __ATTR(value, S_IRUGO, curr_sensor_value_show, NULL);
+static struct switch_attribute curr_alias_attr = __ATTR(alias, S_IRUGO, curr_sensor_alias_show, NULL);
+static struct switch_attribute curr_type_attr = __ATTR(type, S_IRUGO, curr_sensor_type_show, NULL);
+static struct switch_attribute curr_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, curr_sensor_max_show, curr_sensor_max_store);
+static struct switch_attribute curr_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, curr_sensor_min_show, curr_sensor_min_store);
+static struct switch_attribute curr_monitor_flag_attr = __ATTR(monitor_flag, S_IRUGO, curr_sensor_monitor_flag_show, NULL);
+
+static struct attribute *curr_sensor_attrs[] = {
+ &curr_value_attr.attr,
+ &curr_alias_attr.attr,
+ &curr_type_attr.attr,
+ &curr_max_attr.attr,
+ &curr_min_attr.attr,
+ &curr_monitor_flag_attr.attr,
+ NULL,
+};
+
+static struct attribute_group curr_sensor_attr_group = {
+ .attrs = curr_sensor_attrs,
+};
+
+static int curr_sensor_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct curr_sensor_obj_s *curr_sensor;
+
+ curr_sensor = &g_curr_sensor.curr[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "curr%u", index);
+ curr_sensor->obj = switch_kobject_create(name, parent);
+ if (!curr_sensor->obj) {
+ CURR_SENSOR_ERR("create %s object error.\n", name);
+ return -ENOMEM;
+ }
+ curr_sensor->obj->index = index;
+ if (sysfs_create_group(&curr_sensor->obj->kobj, &curr_sensor_attr_group) != 0) {
+ CURR_SENSOR_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&curr_sensor->obj);
+ return -EBADRQC;
+ }
+ CURR_SENSOR_DBG("create %s dir and attrs success.\n", name);
+ return 0;
+}
+
+static void curr_sensor_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct curr_sensor_obj_s *curr_sensor;
+
+ curr_sensor = &g_curr_sensor.curr[index - 1];
+ if (curr_sensor->obj) {
+ sysfs_remove_group(&curr_sensor->obj->kobj, &curr_sensor_attr_group);
+ switch_kobject_delete(&curr_sensor->obj);
+ CURR_SENSOR_DBG("delete curr%u dir and attrs success.\n", index);
+ }
+
+ return;
+}
+
+static int curr_sensor_sub_create_kobj_and_attrs(struct kobject *parent, int curr_num)
+{
+ unsigned int curr_index, i;
+
+ g_curr_sensor.curr = kzalloc(sizeof(struct curr_sensor_obj_s) * curr_num, GFP_KERNEL);
+ if (!g_curr_sensor.curr) {
+ CURR_SENSOR_ERR("kzalloc g_curr_sensor.curr error, curr number: %d.\n", curr_num);
+ return -ENOMEM;
+ }
+
+ for (curr_index = 1; curr_index <= curr_num; curr_index++) {
+ if (curr_sensor_sub_single_create_kobj_and_attrs(parent, curr_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = curr_index; i > 0; i--) {
+ curr_sensor_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_curr_sensor.curr);
+ g_curr_sensor.curr = NULL;
+ return -EBADRQC;
+}
+
+/* create curr[1-n] directory and attributes*/
+static int curr_sensor_sub_create(void)
+{
+ int ret;
+
+ ret = curr_sensor_sub_create_kobj_and_attrs(&g_curr_sensor_obj->kobj,
+ g_curr_sensor.curr_number);
+ return ret;
+}
+
+/* delete curr[1-n] directory and attributes*/
+static void curr_sensor_sub_remove(void)
+{
+ unsigned int curr_index;
+
+ if (g_curr_sensor.curr) {
+ for (curr_index = g_curr_sensor.curr_number; curr_index > 0; curr_index--) {
+ curr_sensor_sub_single_remove_kobj_and_attrs(curr_index);
+ }
+ kfree(g_curr_sensor.curr);
+ g_curr_sensor.curr = NULL;
+ }
+ g_curr_sensor.curr_number = 0;
+ return;
+}
+
+/* create curr_sensor directory and number attributes */
+static int curr_sensor_root_create(void)
+{
+ g_curr_sensor_obj = switch_kobject_create("curr_sensor", NULL);
+ if (!g_curr_sensor_obj) {
+ CURR_SENSOR_ERR("switch_kobject_create curr_sensor error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_curr_sensor_obj->kobj, &curr_sensor_root_attr_group) != 0) {
+ switch_kobject_delete(&g_curr_sensor_obj);
+ CURR_SENSOR_ERR("create curr_sensor dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete curr_sensor directory and number attributes */
+static void curr_sensor_root_remove(void)
+{
+ if (g_curr_sensor_obj) {
+ sysfs_remove_group(&g_curr_sensor_obj->kobj, &curr_sensor_root_attr_group);
+ switch_kobject_delete(&g_curr_sensor_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_curr_sensor_drivers_register(struct s3ip_sysfs_curr_sensor_drivers_s *drv)
+{
+ int ret, curr_num;
+
+ CURR_SENSOR_INFO("s3ip_sysfs_curr_sensor_drivers_register...\n");
+ if (g_curr_sensor_drv) {
+ CURR_SENSOR_ERR("g_curr_sensor_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_main_board_curr_number);
+ g_curr_sensor_drv = drv;
+
+ curr_num = g_curr_sensor_drv->get_main_board_curr_number();
+ if (curr_num <= 0) {
+ CURR_SENSOR_ERR("curr sensor number: %d, don't need to create curr_sensor dirs and attrs.\n",
+ curr_num);
+ g_curr_sensor_drv = NULL;
+ return -EINVAL;
+ }
+ mem_clear(&g_curr_sensor, sizeof(struct curr_sensor_s));
+ g_curr_sensor.curr_number = curr_num;
+ ret = curr_sensor_root_create();
+ if (ret < 0) {
+ CURR_SENSOR_ERR("create curr_sensor root dir and attrs failed, ret: %d\n", ret);
+ g_curr_sensor_drv = NULL;
+ return ret;
+ }
+
+ ret = curr_sensor_sub_create();
+ if (ret < 0) {
+ CURR_SENSOR_ERR("create curr_sensor sub dir and attrs failed, ret: %d\n", ret);
+ curr_sensor_root_remove();
+ g_curr_sensor_drv = NULL;
+ return ret;
+ }
+ CURR_SENSOR_INFO("s3ip_sysfs_curr_sensor_drivers_register success\n");
+ return ret;
+}
+
+void s3ip_sysfs_curr_sensor_drivers_unregister(void)
+{
+ if (g_curr_sensor_drv) {
+ curr_sensor_sub_remove();
+ curr_sensor_root_remove();
+ g_curr_sensor_drv = NULL;
+ CURR_SENSOR_DBG("s3ip_sysfs_curr_sensor_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_curr_sensor_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_curr_sensor_drivers_unregister);
+module_param(g_curr_sensor_loglevel, int, 0644);
+MODULE_PARM_DESC(g_curr_sensor_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/eeprom_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/eeprom_sysfs.c
new file mode 100644
index 000000000000..920cbf0bb824
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/eeprom_sysfs.c
@@ -0,0 +1,417 @@
+/*
+ * An eeprom_sysfs driver for eeprom sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "eeprom_sysfs.h"
+
+static int g_eeprom_loglevel = 0;
+
+#define EEPROM_INFO(fmt, args...) do { \
+ if (g_eeprom_loglevel & INFO) { \
+ printk(KERN_INFO "[EEPROM_SYSFS][func:%s line:%d]"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define EEPROM_ERR(fmt, args...) do { \
+ if (g_eeprom_loglevel & ERR) { \
+ printk(KERN_ERR "[EEPROM_SYSFS][func:%s line:%d]"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define EEPROM_DBG(fmt, args...) do { \
+ if (g_eeprom_loglevel & DBG) { \
+ printk(KERN_DEBUG "[EEPROM_SYSFS][func:%s line:%d]"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct eeprom_obj_s {
+ struct switch_obj *eeprom_obj;
+ struct bin_attribute bin;
+ int eeprom_creat_bin_flag;
+};
+
+struct eeprom_s {
+ unsigned int eeprom_number;
+ struct eeprom_obj_s *eeprom;
+};
+
+static struct eeprom_s g_eeprom;
+static struct switch_obj *g_eeprom_obj = NULL;
+static struct s3ip_sysfs_eeprom_drivers_s *g_eeprom_drv = NULL;
+
+static ssize_t eeprom_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", g_eeprom.eeprom_number);
+}
+
+static ssize_t eeprom_size_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ struct eeprom_obj_s *curr_eeprom;
+
+ EEPROM_DBG("get eeprom size, eeprom index: %u\n", obj->index);
+ curr_eeprom = &g_eeprom.eeprom[obj->index - 1];
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%ld\n", curr_eeprom->bin.size);
+}
+
+static ssize_t eeprom_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eeprom_index;
+
+ check_p(g_eeprom_drv);
+ check_p(g_eeprom_drv->get_eeprom_alias);
+
+ eeprom_index = obj->index;
+ EEPROM_DBG("get eeprom alias, eeprom index: %u\n", eeprom_index);
+ return g_eeprom_drv->get_eeprom_alias(eeprom_index, buf, PAGE_SIZE);
+}
+
+static ssize_t eeprom_tag_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eeprom_index;
+
+ check_p(g_eeprom_drv);
+ check_p(g_eeprom_drv->get_eeprom_tag);
+
+ eeprom_index = obj->index;
+ EEPROM_DBG("get eeprom tag, eeprom index: %u\n", eeprom_index);
+ return g_eeprom_drv->get_eeprom_tag(eeprom_index, buf, PAGE_SIZE);
+}
+
+static ssize_t eeprom_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eeprom_index;
+
+ check_p(g_eeprom_drv);
+ check_p(g_eeprom_drv->get_eeprom_type);
+
+ eeprom_index = obj->index;
+ EEPROM_DBG("get eeprom type, eeprom index: %u\n", eeprom_index);
+ return g_eeprom_drv->get_eeprom_type(eeprom_index, buf, PAGE_SIZE);
+}
+
+static ssize_t eeprom_eeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t count)
+{
+ struct switch_obj *eeprom_obj;
+ ssize_t rd_len;
+ unsigned int eeprom_index;
+
+ check_p(g_eeprom_drv);
+ check_p(g_eeprom_drv->read_eeprom_data);
+
+ eeprom_obj = to_switch_obj(kobj);
+ eeprom_index = eeprom_obj->index;
+ mem_clear(buf, count);
+ rd_len = g_eeprom_drv->read_eeprom_data(eeprom_index, buf, offset, count);
+ if (rd_len < 0) {
+ EEPROM_ERR("read eeprom%u eeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
+ eeprom_index, offset, count, rd_len);
+ return rd_len;
+ }
+
+ EEPROM_DBG("read eeprom%u eeprom data success, offset:0x%llx, read len:%lu, really read len:%ld.\n",
+ eeprom_index, offset, count, rd_len);
+
+ return rd_len;
+}
+
+static ssize_t eeprom_eeprom_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t count)
+{
+ struct switch_obj *eeprom_obj;
+ ssize_t wr_len;
+ unsigned int eeprom_index;
+
+ check_p(g_eeprom_drv);
+ check_p(g_eeprom_drv->write_eeprom_data);
+
+ eeprom_obj = to_switch_obj(kobj);
+ eeprom_index = eeprom_obj->index;
+ wr_len = g_eeprom_drv->write_eeprom_data(eeprom_index, buf, offset, count);
+ if (wr_len < 0) {
+ EEPROM_ERR("write eeprom%u eeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
+ eeprom_index, offset, count, wr_len);
+ return wr_len;
+ }
+
+ EEPROM_DBG("write eeprom%u eeprom data success, offset:0x%llx, write len:%lu, really write len:%ld.\n",
+ eeprom_index, offset, count, wr_len);
+
+ return wr_len;
+}
+
+/************************************eeprom* signal attrs*******************************************/
+static struct switch_attribute eeprom_alias_attr = __ATTR(alias, S_IRUGO | S_IWUSR, eeprom_alias_show, NULL);
+static struct switch_attribute eeprom_tag_attr = __ATTR(tag, S_IRUGO | S_IWUSR, eeprom_tag_show, NULL);
+static struct switch_attribute eeprom_size_attr = __ATTR(size, S_IRUGO, eeprom_size_show, NULL);
+static struct switch_attribute eeprom_type_attr = __ATTR(type, S_IRUGO | S_IWUSR, eeprom_type_show, NULL);
+
+static struct attribute *eeprom_signal_attrs[] = {
+ &eeprom_alias_attr.attr,
+ &eeprom_tag_attr.attr,
+ &eeprom_size_attr.attr,
+ &eeprom_type_attr.attr,
+ NULL,
+};
+
+static struct attribute_group eeprom_signal_attr_group = {
+ .attrs = eeprom_signal_attrs,
+};
+
+/*******************************eeprom dir and attrs*******************************************/
+static struct switch_attribute eeprom_number_attr = __ATTR(number, S_IRUGO, eeprom_number_show, NULL);
+
+static struct attribute *eeprom_dir_attrs[] = {
+ &eeprom_number_attr.attr,
+ NULL,
+};
+
+static struct attribute_group eeprom_eeprom_attr_group = {
+ .attrs = eeprom_dir_attrs,
+};
+
+/* create eeprom* eeprom attributes */
+static int eeprom_sub_single_create_eeprom_attrs(unsigned int index)
+{
+ int ret, eeprom_size;
+ struct eeprom_obj_s *curr_eeprom;
+
+ check_p(g_eeprom_drv->get_eeprom_size);
+ eeprom_size = g_eeprom_drv->get_eeprom_size(index);
+ if (eeprom_size <= 0) {
+ EEPROM_ERR("Invalid eeprom size, eeprom index: %u, eeprom_size: %d\n",
+ index, eeprom_size);
+ return -EINVAL;
+ }
+
+ curr_eeprom = &g_eeprom.eeprom[index - 1];
+ sysfs_bin_attr_init(&curr_eeprom->bin);
+ curr_eeprom->bin.attr.name = "data";
+ curr_eeprom->bin.attr.mode = 0644;
+ curr_eeprom->bin.read = eeprom_eeprom_read;
+ curr_eeprom->bin.write = eeprom_eeprom_write;
+ curr_eeprom->bin.size = eeprom_size;
+
+ ret = sysfs_create_bin_file(&curr_eeprom->eeprom_obj->kobj, &curr_eeprom->bin);
+ if (ret) {
+ EEPROM_ERR("eeprom%u, create eeprom bin error, ret: %d. \n", index, ret);
+ return -EBADRQC;
+ }
+
+ EEPROM_DBG("eeprom%u, create bin file success, eeprom size: %d.\n", index, eeprom_size);
+ curr_eeprom->eeprom_creat_bin_flag = 1;
+ return 0;
+}
+
+static int eeprom_sub_single_create_kobj(struct kobject *parent, unsigned int index)
+{
+ struct eeprom_obj_s *curr_eeprom;
+ char eeprom_dir_name[DIR_NAME_MAX_LEN];
+
+ curr_eeprom = &g_eeprom.eeprom[index - 1];
+ mem_clear(eeprom_dir_name, sizeof(eeprom_dir_name));
+ snprintf(eeprom_dir_name, sizeof(eeprom_dir_name), "eeprom%d", index);
+ curr_eeprom->eeprom_obj = switch_kobject_create(eeprom_dir_name, parent);
+ if (!curr_eeprom->eeprom_obj) {
+ EEPROM_ERR("create eeprom%d object error! \n", index);
+ return -EBADRQC;
+ }
+ curr_eeprom->eeprom_obj->index = index;
+ if (sysfs_create_group(&curr_eeprom->eeprom_obj->kobj, &eeprom_signal_attr_group) != 0) {
+ switch_kobject_delete(&curr_eeprom->eeprom_obj);
+ return -EBADRQC;
+ }
+
+ EEPROM_DBG("create eeprom%d dir and attrs success\n", index);
+ return 0;
+}
+
+/* remove eeprom directory and attributes */
+static void eeprom_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct eeprom_obj_s *curr_eeprom;
+
+ curr_eeprom = &g_eeprom.eeprom[index - 1];
+ if (curr_eeprom->eeprom_obj) {
+ if (curr_eeprom->eeprom_creat_bin_flag) {
+ sysfs_remove_bin_file(&curr_eeprom->eeprom_obj->kobj, &curr_eeprom->bin);
+ curr_eeprom->eeprom_creat_bin_flag = 0;
+ }
+ sysfs_remove_group(&curr_eeprom->eeprom_obj->kobj, &eeprom_signal_attr_group);
+ switch_kobject_delete(&curr_eeprom->eeprom_obj);
+ }
+
+ return;
+}
+
+static int eeprom_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ int ret;
+
+ ret = eeprom_sub_single_create_kobj(parent, index);
+ if (ret < 0) {
+ EEPROM_ERR("create eeprom%d dir error.\n", index);
+ return ret;
+ }
+
+ ret = eeprom_sub_single_create_eeprom_attrs(index);
+ if (ret < 0) {
+ eeprom_sub_single_remove_kobj_and_attrs(index);
+ EEPROM_ERR("create eeprom%d data error.\n", index);
+ return ret;
+ }
+ return 0;
+}
+
+static int eeprom_sub_create_kobj_and_attrs(struct kobject *parent, int eeprom_num)
+{
+ unsigned int eeprom_index, i;
+
+ g_eeprom.eeprom = kzalloc(sizeof(struct eeprom_obj_s) * eeprom_num, GFP_KERNEL);
+ if (!g_eeprom.eeprom) {
+ EEPROM_ERR("kzalloc g_eeprom.eeprom error, eeprom number = %d.\n", eeprom_num);
+ return -ENOMEM;
+ }
+
+ for (eeprom_index = 1; eeprom_index <= eeprom_num; eeprom_index++) {
+ if (eeprom_sub_single_create_kobj_and_attrs(parent, eeprom_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = eeprom_index; i > 0; i--) {
+ eeprom_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_eeprom.eeprom);
+ g_eeprom.eeprom = NULL;
+ return -EBADRQC;
+}
+
+/* create eeprom directory and attributes */
+static int eeprom_sub_create(void)
+{
+ int ret;
+
+ ret = eeprom_sub_create_kobj_and_attrs(&g_eeprom_obj->kobj, g_eeprom.eeprom_number);
+ return ret;
+}
+
+/* delete eeprom directory and attributes */
+static void eeprom_sub_remove(void)
+{
+ unsigned int eeprom_index;
+
+ if (g_eeprom.eeprom) {
+ for (eeprom_index = g_eeprom.eeprom_number; eeprom_index > 0; eeprom_index--) {
+ eeprom_sub_single_remove_kobj_and_attrs(eeprom_index);
+ }
+ kfree(g_eeprom.eeprom);
+ g_eeprom.eeprom = NULL;
+ }
+ g_eeprom.eeprom_number = 0;
+ return;
+}
+
+/* create eeprom directory and attributes */
+static int eeprom_eeprom_create(void)
+{
+ g_eeprom_obj = switch_kobject_create("eeprom", NULL);
+ if (!g_eeprom_obj) {
+ EEPROM_ERR("switch_kobject_create eeprom error!\n");
+ return -ENOMEM;
+ }
+ g_eeprom_obj->index = 0;
+ if (sysfs_create_group(&g_eeprom_obj->kobj, &eeprom_eeprom_attr_group) != 0) {
+ switch_kobject_delete(&g_eeprom_obj);
+ EEPROM_ERR("create eeprom dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete eeprom directory and attributes */
+static void eeprom_eeprom_remove(void)
+{
+ if (g_eeprom_obj) {
+ sysfs_remove_group(&g_eeprom_obj->kobj, &eeprom_eeprom_attr_group);
+ switch_kobject_delete(&g_eeprom_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_eeprom_drivers_register(struct s3ip_sysfs_eeprom_drivers_s *drv)
+{
+ int ret, eeprom_num;
+
+ EEPROM_INFO("s3ip_sysfs_eeprom_drivers_register...\n");
+ if (g_eeprom_drv) {
+ EEPROM_ERR("g_eeprom_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_eeprom_number);
+ g_eeprom_drv = drv;
+
+ eeprom_num = g_eeprom_drv->get_eeprom_number();
+ if (eeprom_num <= 0) {
+ EEPROM_ERR("eeprom number: %d, don't need to create eeprom dirs and attrs.\n", eeprom_num);
+ g_eeprom_drv = NULL;
+ return -EINVAL;
+ }
+
+ mem_clear(&g_eeprom, sizeof(struct eeprom_s));
+ g_eeprom.eeprom_number = eeprom_num;
+ ret = eeprom_eeprom_create();
+ if (ret < 0) {
+ EEPROM_ERR("create eeprom root dir and attrs failed, ret: %d\n", ret);
+ g_eeprom_drv = NULL;
+ return ret;
+ }
+ ret = eeprom_sub_create();
+ if (ret < 0) {
+ EEPROM_ERR("create eeprom sub dir and attrs failed, ret: %d\n", ret);
+ eeprom_eeprom_remove();
+ g_eeprom_drv = NULL;
+ return ret;
+ }
+ EEPROM_INFO("s3ip_sysfs_eeprom_drivers_register success\n");
+ return ret;
+}
+
+void s3ip_sysfs_eeprom_drivers_unregister(void)
+{
+ if (g_eeprom_drv) {
+ eeprom_sub_remove();
+ eeprom_eeprom_remove();
+ g_eeprom_drv = NULL;
+ EEPROM_DBG("s3ip_sysfs_eeprom_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_eeprom_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_eeprom_drivers_unregister);
+module_param(g_eeprom_loglevel, int, 0644);
+MODULE_PARM_DESC(g_eeprom_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/fan_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/fan_sysfs.c
new file mode 100644
index 000000000000..e1b9b56d3ab5
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/fan_sysfs.c
@@ -0,0 +1,777 @@
+/*
+ * An fan_sysfs driver for fan sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "fan_sysfs.h"
+
+static int g_fan_loglevel = 0;
+static bool g_fan_status_debug = 0;
+
+#define FAN_INFO(fmt, args...) do { \
+ if (g_fan_loglevel & INFO) { \
+ printk(KERN_INFO "[FAN_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define FAN_ERR(fmt, args...) do { \
+ if (g_fan_loglevel & ERR) { \
+ printk(KERN_ERR "[FAN_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define FAN_DBG(fmt, args...) do { \
+ if (g_fan_loglevel & DBG) { \
+ printk(KERN_DEBUG "[FAN_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct motor_obj_s {
+ struct switch_obj *obj;
+};
+
+struct fan_obj_s {
+ unsigned int motor_number;
+ struct motor_obj_s *motor;
+ struct switch_obj *obj;
+};
+
+struct fan_s {
+ unsigned int fan_number;
+ struct fan_obj_s *fan;
+};
+
+static struct fan_s g_fan;
+static struct switch_obj *g_fan_obj = NULL;
+static struct s3ip_sysfs_fan_drivers_s *g_fan_drv = NULL;
+
+static ssize_t fan_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", g_fan.fan_number);
+}
+
+static ssize_t fan_motor_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int index;
+
+ index = obj->index;
+ FAN_DBG("fan_motor_number_show, fan index: %u\n", index);
+
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_fan.fan[index - 1].motor_number);
+}
+
+static ssize_t fan_model_name_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_model_name);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_model_name(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_vendor_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_vendor);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_vendor(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_sn_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_serial_number);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_serial_number(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_pn_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_part_number);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_part_number(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_hw_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_hardware_version);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_hardware_version(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fan_index;
+ int ret, res;
+ char debug_file_buf[DEBUG_FILE_SIZE];
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_status);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ ret = g_fan_drv->get_fan_status(fan_index, buf, PAGE_SIZE);
+ if (ret < 0) {
+ FAN_ERR("get fan%u status failed, ret: %d\n", fan_index, ret);
+ return ret;
+ }
+
+ if (g_fan_status_debug) {
+ FAN_INFO("s3ip sysfs fan status debug is enable\n");
+
+ if ((strncmp(buf, SWITCH_DEV_NO_SUPPORT, strlen(SWITCH_DEV_NO_SUPPORT)) == 0) || (strncmp(buf, SWITCH_DEV_ERROR, strlen(SWITCH_DEV_ERROR)) == 0)) {
+ FAN_DBG("fan%d status sysfs unsupport or error\n", fan_index);
+ return ret;
+ }
+
+ if (strcmp(buf, FAN_ABSENT_STR) == 0) {
+ FAN_DBG("fan%d absent, return act value\n", fan_index);
+ return ret;
+ }
+
+ mem_clear(debug_file_buf, sizeof(debug_file_buf));
+ res = dev_debug_file_read(SINGLE_FAN_STATUS_DEBUG_FILE, fan_index, debug_file_buf, sizeof(debug_file_buf));
+ if (res) {
+ FAN_ERR("fan%u status debug file read failed, ret: %d\n", fan_index, res);
+ return ret;
+ }
+
+ if ((strcmp(debug_file_buf, FAN_ABSENT_STR) == 0) || (strcmp(debug_file_buf, FAN_OK_STR) == 0) || (strcmp(debug_file_buf, FAN_NOTOK_STR) == 0)) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s", debug_file_buf);
+ } else {
+ FAN_ERR("fan%d status debug file value err, value: %s, not 0 1 or 2\n", fan_index, debug_file_buf);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static ssize_t fan_present_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_present);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_present(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_led_status_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_led_status);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_led_status(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_led_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int fan_index;
+ int ret, led_status;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->set_fan_led_status);
+
+ fan_index = obj->index;
+ ret = kstrtoint(buf, 0, &led_status);
+ if (ret != 0) {
+ FAN_ERR("invaild fan led status ret: %d, buf: %s.\n", ret, buf);
+ return -EINVAL;
+ }
+ FAN_DBG("fan index: %u, led_status: %d\n", fan_index, led_status);
+ ret = g_fan_drv->set_fan_led_status(fan_index, led_status);
+ if (ret < 0) {
+ FAN_ERR("set fan%u led_status: %d failed, ret: %d\n", fan_index, led_status, ret);
+ return ret;
+ }
+ FAN_DBG("set fan%u led_status: %d success\n", fan_index, led_status);
+ return count;
+}
+
+static ssize_t fan_motor_status_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index, motor_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_motor_status);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ fan_index = p_obj->index;
+ motor_index = obj->index;
+ FAN_DBG("fan index: %u, motor index: %d\n", fan_index, motor_index);
+ return g_fan_drv->get_fan_motor_status(fan_index, motor_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_motor_speed_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index, motor_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_motor_speed);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ fan_index = p_obj->index;
+ motor_index = obj->index;
+ FAN_DBG("fan index: %u, motor index: %d\n", fan_index, motor_index);
+ return g_fan_drv->get_fan_motor_speed(fan_index, motor_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_motor_speed_tolerance_show(struct switch_obj *obj,
+ struct switch_attribute *attr, char *buf)
+{
+ unsigned int fan_index, motor_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_motor_speed_tolerance);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ fan_index = p_obj->index;
+ motor_index = obj->index;
+ FAN_DBG("fan index: %u, motor index: %d\n", fan_index, motor_index);
+ return g_fan_drv->get_fan_motor_speed_tolerance(fan_index, motor_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_motor_speed_target_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index, motor_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_motor_speed_target);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ fan_index = p_obj->index;
+ motor_index = obj->index;
+ FAN_DBG("fan index: %u, motor index: %d\n", fan_index, motor_index);
+ return g_fan_drv->get_fan_motor_speed_target(fan_index, motor_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_motor_speed_max_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index, motor_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_motor_speed_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ fan_index = p_obj->index;
+ motor_index = obj->index;
+ FAN_DBG("fan index: %u, motor index: %d\n", fan_index, motor_index);
+ return g_fan_drv->get_fan_motor_speed_max(fan_index, motor_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_motor_speed_min_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int fan_index, motor_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_motor_speed_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ fan_index = p_obj->index;
+ motor_index = obj->index;
+ FAN_DBG("fan index: %u, motor index: %d\n", fan_index, motor_index);
+ return g_fan_drv->get_fan_motor_speed_min(fan_index, motor_index, buf, PAGE_SIZE);
+}
+
+ssize_t fan_ratio_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_ratio);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_ratio(fan_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fan_ratio_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int fan_index;
+ int ret, ratio;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->set_fan_ratio);
+
+ fan_index = obj->index;
+
+ ret = kstrtoint(buf, 0, &ratio);
+ if (ret != 0) {
+ FAN_ERR("invaild fan ratio ret: %d, buf: %s.\n", ret, buf);
+ return -EINVAL;
+ }
+
+ if (ratio < 0 || ratio > 100) {
+ FAN_ERR("param invalid, can not set ratio: %d.\n", ratio);
+ return -EINVAL;
+ }
+ FAN_DBG("fan index: %u, ratio: %d\n", fan_index, ratio);
+ ret = g_fan_drv->set_fan_ratio(fan_index, ratio);
+ if (ret < 0) {
+ FAN_ERR("set fan%u ratio: %d failed, ret: %d\n", fan_index, ratio, ret);
+ return ret;
+ }
+ FAN_DBG("set fan%u, ratio: %d success\n", fan_index, ratio);
+ return count;
+}
+
+ssize_t fan_direction_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fan_index;
+
+ check_p(g_fan_drv);
+ check_p(g_fan_drv->get_fan_direction);
+
+ fan_index = obj->index;
+ FAN_DBG("fan index: %u\n", fan_index);
+ return g_fan_drv->get_fan_direction(fan_index, buf, PAGE_SIZE);
+}
+
+/************************************fan dir and attrs*******************************************/
+static struct switch_attribute fan_number_att = __ATTR(number, S_IRUGO, fan_number_show, NULL);
+
+static struct attribute *fan_dir_attrs[] = {
+ &fan_number_att.attr,
+ NULL,
+};
+
+static struct attribute_group fan_root_attr_group = {
+ .attrs = fan_dir_attrs,
+};
+
+/*******************************fan1 fan2 dir and attrs*******************************************/
+static struct switch_attribute fan_model_name_attr = __ATTR(model_name, S_IRUGO, fan_model_name_show, NULL);
+static struct switch_attribute fan_vendor_attr = __ATTR(vendor, S_IRUGO, fan_vendor_show, NULL);
+static struct switch_attribute fan_sn_attr = __ATTR(serial_number, S_IRUGO, fan_sn_show, NULL);
+static struct switch_attribute fan_pn_attr = __ATTR(part_number, S_IRUGO, fan_pn_show, NULL);
+static struct switch_attribute fan_hw_attr = __ATTR(hardware_version, S_IRUGO, fan_hw_show, NULL);
+static struct switch_attribute fan_num_motors_attr = __ATTR(motor_number, S_IRUGO, fan_motor_number_show, NULL);
+static struct switch_attribute fan_status_attr = __ATTR(status, S_IRUGO, fan_status_show, NULL);
+static struct switch_attribute fan_present_attr = __ATTR(present, S_IRUGO, fan_present_show, NULL);
+static struct switch_attribute fan_led_status_attr = __ATTR(led_status, S_IRUGO | S_IWUSR, fan_led_status_show, fan_led_status_store);
+static struct switch_attribute fan_direction_attr = __ATTR(direction, S_IRUGO, fan_direction_show, NULL);
+static struct switch_attribute fan_ratio_attr = __ATTR(ratio, S_IRUGO | S_IWUSR, fan_ratio_show, fan_ratio_store);
+
+static struct attribute *fan_attrs[] = {
+ &fan_model_name_attr.attr,
+ &fan_vendor_attr.attr,
+ &fan_sn_attr.attr,
+ &fan_pn_attr.attr,
+ &fan_hw_attr.attr,
+ &fan_num_motors_attr.attr,
+ &fan_status_attr.attr,
+ &fan_present_attr.attr,
+ &fan_led_status_attr.attr,
+ &fan_direction_attr.attr,
+ &fan_ratio_attr.attr,
+ NULL,
+};
+
+static struct attribute_group fan_attr_group = {
+ .attrs = fan_attrs,
+};
+
+/*******************************motor1 motor2 dir and attrs*******************************************/
+static struct switch_attribute motor_status_attr = __ATTR(status, S_IRUGO, fan_motor_status_show, NULL);
+static struct switch_attribute motor_speed_attr = __ATTR(speed, S_IRUGO, fan_motor_speed_show, NULL);
+static struct switch_attribute motor_speed_tolerance_attr = __ATTR(speed_tolerance, S_IRUGO, fan_motor_speed_tolerance_show, NULL);
+static struct switch_attribute motor_speed_target_attr = __ATTR(speed_target, S_IRUGO, fan_motor_speed_target_show, NULL);
+static struct switch_attribute motor_speed_max_attr = __ATTR(speed_max, S_IRUGO, fan_motor_speed_max_show, NULL);
+static struct switch_attribute motor_speed_min_attr = __ATTR(speed_min, S_IRUGO, fan_motor_speed_min_show, NULL);
+
+static struct attribute *motor_attrs[] = {
+ &motor_status_attr.attr,
+ &motor_speed_attr.attr,
+ &motor_speed_tolerance_attr.attr,
+ &motor_speed_target_attr.attr,
+ &motor_speed_max_attr.attr,
+ &motor_speed_min_attr.attr,
+ NULL,
+};
+
+static struct attribute_group motor_attr_group = {
+ .attrs = motor_attrs,
+};
+
+static void fanindex_single_motor_remove_kobj_and_attrs(struct fan_obj_s *curr_fan, unsigned int motor_index)
+{
+ struct motor_obj_s *curr_motor; /* point to motor1 motor2...*/
+
+ curr_motor = &curr_fan->motor[motor_index - 1];
+ if (curr_motor->obj) {
+ sysfs_remove_group(&curr_motor->obj->kobj, &motor_attr_group);
+ switch_kobject_delete(&curr_motor->obj);
+ FAN_DBG("delete fan%u motor%u dir and attrs success.\n", curr_fan->obj->index,
+ motor_index);
+ }
+ return;
+}
+
+static int fanindex_single_motor_create_kobj_and_attrs(struct fan_obj_s *curr_fan, unsigned int motor_index)
+{
+ char name[8];
+ struct motor_obj_s *curr_motor; /* point to motor1 motor2...*/
+
+ curr_motor = &curr_fan->motor[motor_index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "motor%u", motor_index);
+ curr_motor->obj = switch_kobject_create(name, &curr_fan->obj->kobj);
+ if (!curr_motor->obj) {
+ FAN_ERR("create fan%u, motor%u object error!\n", curr_fan->obj->index, motor_index);
+ return -ENOMEM;
+ }
+
+ curr_motor->obj->index = motor_index;
+ if (sysfs_create_group(&curr_motor->obj->kobj, &motor_attr_group) != 0) {
+ FAN_ERR("create fan%u, motor%u attrs error.\n", curr_fan->obj->index, motor_index);
+ switch_kobject_delete(&curr_motor->obj);
+ return -EBADRQC;
+ }
+ FAN_DBG("create fan%u, motor%u dir and attrs success.\n", curr_fan->obj->index, motor_index);
+ return 0;
+}
+
+/* create motor[1-n] directory and attributes in fan directory */
+static int fanindex_motor_create_kobj_and_attrs(struct fan_obj_s *curr_fan)
+{
+ unsigned int motor_index, i, motor_num;
+
+ motor_num = curr_fan->motor_number;
+ curr_fan->motor = kzalloc(sizeof(struct motor_obj_s) * motor_num, GFP_KERNEL);
+ if (!curr_fan->motor) {
+ FAN_ERR("kzalloc motor error, fan index: %u, motor number: %d.\n",
+ curr_fan->obj->index, motor_num);
+ return -ENOMEM;
+ }
+ for (motor_index = 1; motor_index <= motor_num; motor_index++) {
+ if (fanindex_single_motor_create_kobj_and_attrs(curr_fan, motor_index) != 0) {
+ goto motor_error;
+ }
+ }
+ return 0;
+motor_error:
+ for (i = motor_index; i > 0; i--) {
+ fanindex_single_motor_remove_kobj_and_attrs(curr_fan, i);
+ }
+ kfree(curr_fan->motor);
+ curr_fan->motor = NULL;
+ return -EBADRQC;
+}
+
+/* delete motor[1-n] directory and attributes in fan directory */
+static void fanindex_motor_remove_kobj_and_attrs(struct fan_obj_s *curr_fan)
+{
+ unsigned int motor_index, motor_num;
+
+ if (curr_fan->motor) {
+ motor_num = curr_fan->motor_number;
+ for (motor_index = motor_num; motor_index > 0; motor_index--) {
+ fanindex_single_motor_remove_kobj_and_attrs(curr_fan, motor_index);
+ }
+ kfree(curr_fan->motor);
+ curr_fan->motor = NULL;
+ }
+
+ return;
+}
+
+/* create motor[1-n] directory and attributes */
+static int fan_motor_create(void)
+{
+ int fan_num, motor_num;
+ unsigned int fan_index, i;
+ struct fan_obj_s *curr_fan; /* point to fan1 fan2...*/
+
+ fan_num = g_fan.fan_number;
+ if (fan_num <= 0) {
+ FAN_DBG("fan number: %d, skip to create motor* dirs and attrs.\n", fan_num);
+ return 0;
+ }
+
+ check_p(g_fan_drv->get_fan_motor_number);
+
+ for (fan_index = 1; fan_index <= fan_num; fan_index++) {
+ motor_num = g_fan_drv->get_fan_motor_number(fan_index);
+ if (motor_num <= 0) {
+ FAN_DBG("fan%u motor number: %d, don't need to create motor* dirs and attrs.\n",
+ fan_index, motor_num);
+ continue;
+ }
+ curr_fan = &g_fan.fan[fan_index - 1];
+ curr_fan->motor_number = motor_num;
+ if (fanindex_motor_create_kobj_and_attrs(curr_fan) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = fan_index; i > 0; i--) {
+ curr_fan = &g_fan.fan[i - 1];
+ fanindex_motor_remove_kobj_and_attrs(curr_fan);
+ }
+ return -EBADRQC;
+}
+
+/* delete motor[1-n] directory and attributes */
+static void fan_motor_remove(void)
+{
+ unsigned int fan_index;
+ struct fan_obj_s *curr_fan;
+
+ if (g_fan.fan) {
+ for (fan_index = g_fan.fan_number; fan_index > 0; fan_index--) {
+ curr_fan = &g_fan.fan[fan_index - 1];
+ fanindex_motor_remove_kobj_and_attrs(curr_fan);
+ curr_fan->motor_number = 0;
+ }
+ }
+ return;
+}
+
+static int fan_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct fan_obj_s *curr_fan;
+
+ curr_fan = &g_fan.fan[index - 1];
+ if (curr_fan->obj) {
+ sysfs_remove_group(&curr_fan->obj->kobj, &fan_attr_group);
+ switch_kobject_delete(&curr_fan->obj);
+ FAN_DBG("delete fan%u dir and attrs success.\n", index);
+ }
+ return 0;
+}
+
+static int fan_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ char name[8];
+ struct fan_obj_s *curr_fan;
+
+ curr_fan = &g_fan.fan[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "fan%u", index);
+ curr_fan->obj = switch_kobject_create(name, parent);
+ if (!curr_fan->obj) {
+ FAN_ERR("create %s object error!\n", name);
+ return -ENOMEM;
+ }
+
+ curr_fan->obj->index = index;
+ if (sysfs_create_group(&curr_fan->obj->kobj, &fan_attr_group) != 0) {
+ FAN_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&curr_fan->obj);
+ return -EBADRQC;
+ }
+ FAN_DBG("create %s dir and attrs success.\n", name);
+ return 0;
+}
+
+/* create fan[1-n] directory and attributes */
+static int fan_sub_create_kobj_and_attrs(struct kobject *parent, int fan_num)
+{
+ unsigned int fan_index, i;
+
+ g_fan.fan = kzalloc(sizeof(struct fan_obj_s) * fan_num, GFP_KERNEL);
+ if (!g_fan.fan) {
+ FAN_ERR("kzalloc fan.fan error, fan number: %d.\n", fan_num);
+ return -ENOMEM;
+ }
+
+ for (fan_index = 1; fan_index <= fan_num; fan_index++) {
+ if (fan_sub_single_create_kobj_and_attrs(parent, fan_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = fan_index; i > 0; i--) {
+ fan_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_fan.fan);
+ g_fan.fan = NULL;
+ return -EBADRQC;
+}
+
+static int fan_sub_create(void)
+{
+ int ret;
+
+ ret = fan_sub_create_kobj_and_attrs(&g_fan_obj->kobj, g_fan.fan_number);
+ return ret;
+}
+
+/* delete fan[1-n] directory and attributes */
+static void fan_sub_remove(void)
+{
+ unsigned int fan_index;
+
+ if (g_fan.fan) {
+ for (fan_index = g_fan.fan_number; fan_index > 0; fan_index--) {
+ fan_sub_single_remove_kobj_and_attrs(fan_index);
+ }
+ kfree(g_fan.fan);
+ g_fan.fan = NULL;
+ }
+ g_fan.fan_number = 0;
+
+ return;
+}
+
+/* create fan directory and number attributes */
+static int fan_root_create(void)
+{
+ g_fan_obj = switch_kobject_create("fan", NULL);
+ if (!g_fan_obj) {
+ FAN_ERR("switch_kobject_create fan error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_fan_obj->kobj, &fan_root_attr_group) != 0) {
+ switch_kobject_delete(&g_fan_obj);
+ FAN_ERR("create fan dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete fan directory and number attributes */
+static void fan_root_remove(void)
+{
+ if (g_fan_obj) {
+ sysfs_remove_group(&g_fan_obj->kobj, &fan_root_attr_group);
+ switch_kobject_delete(&g_fan_obj);
+ FAN_DBG("delete fan dir and attrs success.\n");
+ }
+ return;
+}
+
+int s3ip_sysfs_fan_drivers_register(struct s3ip_sysfs_fan_drivers_s *drv)
+{
+ int ret, fan_num;
+
+ FAN_INFO("s3ip_sysfs_fan_drivers_register...\n");
+ if (g_fan_drv) {
+ FAN_ERR("g_fan_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_fan_number);
+ g_fan_drv = drv;
+
+ fan_num = g_fan_drv->get_fan_number();
+ if (fan_num <= 0) {
+ FAN_ERR("fan number: %d, don't need to create fan dirs and attrs.\n", fan_num);
+ g_fan_drv = NULL;
+ return -EINVAL;
+ }
+
+ mem_clear(&g_fan, sizeof(struct fan_s));
+ g_fan.fan_number = fan_num;
+ ret = fan_root_create();
+ if (ret < 0) {
+ FAN_ERR("create fan root dir and attrs failed, ret: %d\n", ret);
+ g_fan_drv = NULL;
+ return ret;
+ }
+
+ ret = fan_sub_create();
+ if (ret < 0) {
+ FAN_ERR("create fan sub dir and attrs failed, ret: %d\n", ret);
+ fan_root_remove();
+ g_fan_drv = NULL;
+ return ret;
+ }
+
+ ret = fan_motor_create();
+ if (ret < 0) {
+ FAN_ERR("create fan motor dir and attrs failed, ret: %d\n", ret);
+ fan_sub_remove();
+ fan_root_remove();
+ g_fan_drv = NULL;
+ return ret;
+ }
+ FAN_INFO("s3ip_sysfs_fan_drivers_register success.\n");
+ return 0;
+}
+
+void s3ip_sysfs_fan_drivers_unregister(void)
+{
+ if (g_fan_drv) {
+ fan_motor_remove();
+ fan_sub_remove();
+ fan_root_remove();
+ g_fan_drv = NULL;
+ FAN_DBG("s3ip_sysfs_fan_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_fan_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_fan_drivers_unregister);
+module_param(g_fan_loglevel, int, 0644);
+MODULE_PARM_DESC(g_fan_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
+module_param(g_fan_status_debug, bool, 0644);
+MODULE_PARM_DESC(g_fan_status_debug, "the fan present debug switch(0: disable, 1:enable, defalut: 0).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/fpga_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/fpga_sysfs.c
new file mode 100644
index 000000000000..d0ec8dfc62f7
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/fpga_sysfs.c
@@ -0,0 +1,345 @@
+/*
+ * An fpga_sysfs driver for fpga sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "fpga_sysfs.h"
+
+static int g_fpga_loglevel = 0;
+
+#define FPGA_INFO(fmt, args...) do { \
+ if (g_fpga_loglevel & INFO) { \
+ printk(KERN_INFO "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define FPGA_ERR(fmt, args...) do { \
+ if (g_fpga_loglevel & ERR) { \
+ printk(KERN_ERR "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define FPGA_DBG(fmt, args...) do { \
+ if (g_fpga_loglevel & DBG) { \
+ printk(KERN_DEBUG "[FPGA_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct fpga_obj_s {
+ struct switch_obj *obj;
+};
+
+struct fpga_s {
+ unsigned int fpga_number;
+ struct fpga_obj_s *fpga;
+};
+
+static struct fpga_s g_fpga;
+static struct switch_obj *g_fpga_obj = NULL;
+static struct s3ip_sysfs_fpga_drivers_s *g_fpga_drv = NULL;
+
+static ssize_t fpga_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_fpga.fpga_number);
+}
+
+static ssize_t fpga_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fpga_index;
+
+ check_p(g_fpga_drv);
+ check_p(g_fpga_drv->get_main_board_fpga_alias);
+
+ fpga_index = obj->index;
+ FPGA_DBG("fpga index: %u\n", fpga_index);
+ return g_fpga_drv->get_main_board_fpga_alias(fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fpga_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fpga_index;
+
+ check_p(g_fpga_drv);
+ check_p(g_fpga_drv->get_main_board_fpga_type);
+
+ fpga_index = obj->index;
+ FPGA_DBG("fpga index: %u\n", fpga_index);
+ return g_fpga_drv->get_main_board_fpga_type(fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fpga_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fpga_index;
+
+ check_p(g_fpga_drv);
+ check_p(g_fpga_drv->get_main_board_fpga_firmware_version);
+
+ fpga_index = obj->index;
+ FPGA_DBG("fpga index: %u\n", fpga_index);
+ return g_fpga_drv->get_main_board_fpga_firmware_version(fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fpga_board_version_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fpga_index;
+
+ check_p(g_fpga_drv);
+ check_p(g_fpga_drv->get_main_board_fpga_board_version);
+
+ fpga_index = obj->index;
+ FPGA_DBG("fpga index: %u\n", fpga_index);
+ return g_fpga_drv->get_main_board_fpga_board_version(fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fpga_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int fpga_index;
+
+ check_p(g_fpga_drv);
+ check_p(g_fpga_drv->get_main_board_fpga_test_reg);
+
+ fpga_index = obj->index;
+ FPGA_DBG("fpga index: %u\n", fpga_index);
+ return g_fpga_drv->get_main_board_fpga_test_reg(fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t fpga_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int fpga_index, value;
+ int ret;
+
+ check_p(g_fpga_drv);
+ check_p(g_fpga_drv->set_main_board_fpga_test_reg);
+
+ fpga_index = obj->index;
+ sscanf(buf, "0x%x", &value);
+ ret = g_fpga_drv->set_main_board_fpga_test_reg(fpga_index, value);
+ if (ret < 0) {
+ FPGA_ERR("set fpga%u test reg failed, value:0x%x, ret: %d.\n", fpga_index, value, ret);
+ return ret;
+ }
+ FPGA_DBG("set fpga%u test reg success, value: 0x%x.\n", fpga_index, value);
+ return count;
+}
+
+/************************************fpga dir and attrs*******************************************/
+static struct switch_attribute fpga_number_att = __ATTR(number, S_IRUGO, fpga_number_show, NULL);
+
+static struct attribute *fpga_dir_attrs[] = {
+ &fpga_number_att.attr,
+ NULL,
+};
+
+static struct attribute_group fpga_root_attr_group = {
+ .attrs = fpga_dir_attrs,
+};
+
+/*******************************fpga[1-n] dir and attrs*******************************************/
+static struct switch_attribute fpga_alias_attr = __ATTR(alias, S_IRUGO, fpga_alias_show, NULL);
+static struct switch_attribute fpga_type_attr = __ATTR(type, S_IRUGO, fpga_type_show, NULL);
+static struct switch_attribute fpga_fw_version_attr = __ATTR(firmware_version, S_IRUGO, fpga_fw_version_show, NULL);
+static struct switch_attribute fpga_board_version_attr = __ATTR(board_version, S_IRUGO, fpga_board_version_show, NULL);
+static struct switch_attribute fpga_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, fpga_test_reg_show, fpga_test_reg_store);
+
+static struct attribute *fpga_attrs[] = {
+ &fpga_alias_attr.attr,
+ &fpga_type_attr.attr,
+ &fpga_fw_version_attr.attr,
+ &fpga_board_version_attr.attr,
+ &fpga_test_reg_attr.attr,
+ NULL,
+};
+
+static struct attribute_group fpga_attr_group = {
+ .attrs = fpga_attrs,
+};
+
+static int fpga_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct fpga_obj_s *curr_fpga;
+
+ curr_fpga = &g_fpga.fpga[index - 1];
+ if (curr_fpga->obj) {
+ sysfs_remove_group(&curr_fpga->obj->kobj, &fpga_attr_group);
+ switch_kobject_delete(&curr_fpga->obj);
+ FPGA_DBG("delete fpga%u dir and attrs success.\n", index);
+ }
+ return 0;
+}
+
+static int fpga_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ char name[8];
+ struct fpga_obj_s *curr_fpga;
+
+ curr_fpga = &g_fpga.fpga[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "fpga%u", index);
+ curr_fpga->obj = switch_kobject_create(name, parent);
+ if (!curr_fpga->obj) {
+ FPGA_ERR("create %s object error!\n", name);
+ return -EBADRQC;
+ }
+ curr_fpga->obj->index = index;
+ if (sysfs_create_group(&curr_fpga->obj->kobj, &fpga_attr_group) != 0) {
+ FPGA_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&curr_fpga->obj);
+ return -EBADRQC;
+ }
+ FPGA_DBG("create %s dir and attrs success.\n", name);
+ return 0;
+}
+
+static int fpga_sub_create_kobj_and_attrs(struct kobject *parent, int fpga_num)
+{
+ unsigned int fpga_index, i;
+
+ g_fpga.fpga = kzalloc(sizeof(struct fpga_obj_s) * fpga_num, GFP_KERNEL);
+ if (!g_fpga.fpga) {
+ FPGA_ERR("kzalloc g_fpga.fpga error, fpga number = %d.\n", fpga_num);
+ return -ENOMEM;
+ }
+
+ for (fpga_index = 1; fpga_index <= fpga_num; fpga_index++) {
+ if (fpga_sub_single_create_kobj_and_attrs(parent, fpga_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = fpga_index; i > 0; i--) {
+ fpga_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_fpga.fpga);
+ g_fpga.fpga = NULL;
+ return -EBADRQC;
+}
+
+/* create fpga[1-n] directory and attributes*/
+static int fpga_sub_create(void)
+{
+ int ret;
+
+ ret = fpga_sub_create_kobj_and_attrs(&g_fpga_obj->kobj, g_fpga.fpga_number);
+ return ret;
+}
+
+/* delete fpga[1-n] directory and attributes*/
+static void fpga_sub_remove(void)
+{
+ unsigned int fpga_index;
+
+ if (g_fpga.fpga) {
+ for (fpga_index = g_fpga.fpga_number; fpga_index > 0; fpga_index--) {
+ fpga_sub_single_remove_kobj_and_attrs(fpga_index);
+ }
+ kfree(g_fpga.fpga);
+ g_fpga.fpga = NULL;
+ }
+ g_fpga.fpga_number = 0;
+ return;
+}
+
+/* create fpga directory and number attributes */
+static int fpga_root_create(void)
+{
+ g_fpga_obj = switch_kobject_create("fpga", NULL);
+ if (!g_fpga_obj) {
+ FPGA_ERR("switch_kobject_create fpga error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_fpga_obj->kobj, &fpga_root_attr_group) != 0) {
+ switch_kobject_delete(&g_fpga_obj);
+ FPGA_ERR("create fpga dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete fpga directory and number attributes */
+static void fpga_root_remove(void)
+{
+ if (g_fpga_obj) {
+ sysfs_remove_group(&g_fpga_obj->kobj, &fpga_root_attr_group);
+ switch_kobject_delete(&g_fpga_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_fpga_drivers_register(struct s3ip_sysfs_fpga_drivers_s *drv)
+{
+ int ret, fpga_num;
+
+ FPGA_INFO("s3ip_sysfs_fpga_drivers_register...\n");
+ if (g_fpga_drv) {
+ FPGA_ERR("g_fpga_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_main_board_fpga_number);
+ g_fpga_drv = drv;
+
+ fpga_num = g_fpga_drv->get_main_board_fpga_number();
+ if (fpga_num <= 0) {
+ FPGA_ERR("fpga number: %d, don't need to create fpga dirs and attrs.\n", fpga_num);
+ g_fpga_drv = NULL;
+ return -EINVAL;
+ }
+
+ mem_clear(&g_fpga, sizeof(struct fpga_s));
+ g_fpga.fpga_number = fpga_num;
+ ret = fpga_root_create();
+ if (ret < 0) {
+ FPGA_ERR("create fpga root dir and attrs failed, ret: %d\n", ret);
+ g_fpga_drv = NULL;
+ return ret;
+ }
+ ret = fpga_sub_create();
+ if (ret < 0) {
+ FPGA_ERR("create fpga sub dir and attrs failed, ret: %d\n", ret);
+ fpga_root_remove();
+ g_fpga_drv = NULL;
+ return ret;
+ }
+ FPGA_INFO("s3ip_sysfs_fpga_drivers_register success\n");
+ return 0;
+}
+
+void s3ip_sysfs_fpga_drivers_unregister(void)
+{
+ if (g_fpga_drv) {
+ fpga_sub_remove();
+ fpga_root_remove();
+ g_fpga_drv = NULL;
+ FPGA_DBG("s3ip_sysfs_fpga_drivers_unregister success.\n");
+ }
+
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_fpga_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_fpga_drivers_unregister);
+module_param(g_fpga_loglevel, int, 0644);
+MODULE_PARM_DESC(g_fpga_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/cpld_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/cpld_sysfs.h
new file mode 100644
index 000000000000..2638b18c6f4c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/cpld_sysfs.h
@@ -0,0 +1,36 @@
+/*
+ * A header definition for cpld_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _CPLD_SYSFS_H_
+#define _CPLD_SYSFS_H_
+
+struct s3ip_sysfs_cpld_drivers_s {
+ int (*get_main_board_cpld_number)(void);
+ ssize_t (*get_main_board_cpld_alias)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_type)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_firmware_version)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_board_version)(unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_main_board_cpld_test_reg)(unsigned int cpld_index, char *buf, size_t count);
+ int (*set_main_board_cpld_test_reg)(unsigned int cpld_index, unsigned int value);
+};
+
+extern int s3ip_sysfs_cpld_drivers_register(struct s3ip_sysfs_cpld_drivers_s *drv);
+extern void s3ip_sysfs_cpld_drivers_unregister(void);
+#endif /*_CPLD_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/curr_sensor_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/curr_sensor_sysfs.h
new file mode 100644
index 000000000000..fc9bb4948a14
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/curr_sensor_sysfs.h
@@ -0,0 +1,38 @@
+/*
+ * A header definition for curr_sensor_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _CURR_SENSOR_SYSFS_H_
+#define _CURR_SENSOR_SYSFS_H_
+
+struct s3ip_sysfs_curr_sensor_drivers_s {
+ int (*get_main_board_curr_number)(void);
+ ssize_t (*get_main_board_curr_alias)(unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_main_board_curr_type)(unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_main_board_curr_max)(unsigned int curr_index, char *buf, size_t count);
+ int (*set_main_board_curr_max)(unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_curr_min)(unsigned int curr_index, char *buf, size_t count);
+ int (*set_main_board_curr_min)(unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_curr_value)(unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_main_board_curr_monitor_flag)(unsigned int curr_index, char *buf, size_t count);
+};
+
+extern int s3ip_sysfs_curr_sensor_drivers_register(struct s3ip_sysfs_curr_sensor_drivers_s *drv);
+extern void s3ip_sysfs_curr_sensor_drivers_unregister(void);
+#endif /*_CURR_SENSOR_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/eeprom_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/eeprom_sysfs.h
new file mode 100644
index 000000000000..5ebb79afdc9a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/eeprom_sysfs.h
@@ -0,0 +1,36 @@
+/*
+ * A header definition for eeprom_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _EEPROM_SYSFS_H_
+#define _EEPROM_SYSFS_H_
+
+struct s3ip_sysfs_eeprom_drivers_s {
+ int (*get_eeprom_number)(void);
+ ssize_t (*get_eeprom_alias)(unsigned int e2_index, char *buf, size_t count);
+ ssize_t (*get_eeprom_tag)(unsigned int e2_index, char *buf, size_t count);
+ ssize_t (*get_eeprom_type)(unsigned int e2_index, char *buf, size_t count);
+ int (*get_eeprom_size)(unsigned int e2_index);
+ ssize_t (*read_eeprom_data)(unsigned int e2_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*write_eeprom_data)(unsigned int e2_index, char *buf, loff_t offset, size_t count);
+};
+
+extern int s3ip_sysfs_eeprom_drivers_register(struct s3ip_sysfs_eeprom_drivers_s *drv);
+extern void s3ip_sysfs_eeprom_drivers_unregister(void);
+#endif /*_EEPROM_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/fan_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/fan_sysfs.h
new file mode 100644
index 000000000000..f89afabd86bd
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/fan_sysfs.h
@@ -0,0 +1,53 @@
+/*
+ * A header definition for fan_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _FAN_SYSFS_H_
+#define _FAN_SYSFS_H_
+
+struct s3ip_sysfs_fan_drivers_s {
+ int (*get_fan_number)(void);
+ int (*get_fan_motor_number)(unsigned int fan_index);
+ ssize_t (*get_fan_model_name)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_vendor)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_serial_number)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_part_number)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_hardware_version)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_status)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_present)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_led_status)(unsigned int fan_index, char *buf, size_t count);
+ int (*set_fan_led_status)(unsigned int fan_index, int status);
+ ssize_t (*get_fan_direction)(unsigned int fan_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_status)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_tolerance)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_target)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_max)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_motor_speed_min)(unsigned int fan_index, unsigned int motor_index, char *buf, size_t count);
+ ssize_t (*get_fan_ratio)(unsigned int fan_index, char *buf, size_t count);
+ int (*set_fan_ratio)(unsigned int fan_index, int ratio);
+};
+
+extern int s3ip_sysfs_fan_drivers_register(struct s3ip_sysfs_fan_drivers_s *drv);
+extern void s3ip_sysfs_fan_drivers_unregister(void);
+#define SINGLE_FAN_STATUS_DEBUG_FILE "/etc/sonic/.status_fan_%d"
+#define FAN_ABSENT_STR "0\n"
+#define FAN_OK_STR "1\n"
+#define FAN_NOTOK_STR "2\n"
+#endif /*_FAN_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/fpga_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/fpga_sysfs.h
new file mode 100644
index 000000000000..5335a5b0fa4c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/fpga_sysfs.h
@@ -0,0 +1,36 @@
+/*
+ * A header definition for fpga_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _FPGA_SYSFS_H_
+#define _FPGA_SYSFS_H_
+
+struct s3ip_sysfs_fpga_drivers_s {
+ int (*get_main_board_fpga_number)(void);
+ ssize_t (*get_main_board_fpga_alias)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_type)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_firmware_version)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_board_version)(unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_main_board_fpga_test_reg)(unsigned int fpga_index, char *buf, size_t count);
+ int (*set_main_board_fpga_test_reg)(unsigned int fpga_index, unsigned int value);
+};
+
+extern int s3ip_sysfs_fpga_drivers_register(struct s3ip_sysfs_fpga_drivers_s *drv);
+extern void s3ip_sysfs_fpga_drivers_unregister(void);
+#endif /*_FPGA_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/psu_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/psu_sysfs.h
new file mode 100644
index 000000000000..c89de1cea6a2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/psu_sysfs.h
@@ -0,0 +1,73 @@
+/*
+ * A header definition for psu_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _PSU_SYSFS_H_
+#define _PSU_SYSFS_H_
+
+struct s3ip_sysfs_psu_drivers_s {
+ int (*get_psu_number)(void);
+ int (*get_psu_temp_number)(unsigned int psu_index);
+ ssize_t (*get_psu_model_name)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_vendor)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_date)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_hw_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_alarm)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_serial_number)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_part_number)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_hardware_version)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_type)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_curr)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_vol)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_power)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_curr)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_vol)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_power)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_max_power)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_present_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_status_pmbus)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_in_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_out_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_fan_speed)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_fan_ratio)(unsigned int psu_index, char *buf, size_t count);
+ int (*set_psu_fan_ratio)(unsigned int psu_index, int ratio);
+ ssize_t (*get_psu_fan_direction)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_led_status)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_fan_speed_cal)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_temp_alias)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_psu_temp_type)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_psu_temp_max)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_psu_temp_max)(unsigned int psu_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_psu_temp_min)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_psu_temp_min)(unsigned int psu_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_psu_temp_value)(unsigned int psu_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_psu_attr_threshold)(unsigned int psu_index, unsigned int type, char *buf, size_t count);
+ int (*get_psu_eeprom_size)(unsigned int psu_index);
+ ssize_t (*read_psu_eeprom_data)(unsigned int psu_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*get_psu_blackbox_info)(unsigned int psu_index, char *buf, size_t count);
+ ssize_t (*get_psu_pmbus_info)(unsigned int psu_index, char *buf, size_t count);
+ int (*clear_psu_blackbox)(unsigned int psu_index, uint8_t value);
+};
+
+extern int s3ip_sysfs_psu_drivers_register(struct s3ip_sysfs_psu_drivers_s *drv);
+extern void s3ip_sysfs_psu_drivers_unregister(void);
+#define SINGLE_PSU_PRESENT_DEBUG_FILE "/etc/sonic/.present_psu_%d"
+
+#endif /*_PSU_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/slot_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/slot_sysfs.h
new file mode 100644
index 000000000000..e5cba548f224
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/slot_sysfs.h
@@ -0,0 +1,80 @@
+/*
+ * A header definition for slot_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SLOT_SYSFS_H_
+#define _SLOT_SYSFS_H_
+
+struct s3ip_sysfs_slot_drivers_s {
+ int (*get_slot_number)(void);
+ int (*get_slot_temp_number)(unsigned int slot_index);
+ int (*get_slot_vol_number)(unsigned int slot_index);
+ int (*get_slot_curr_number)(unsigned int slot_index);
+ int (*get_slot_cpld_number)(unsigned int slot_index);
+ int (*get_slot_fpga_number)(unsigned int slot_index);
+ ssize_t (*get_slot_model_name)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_vendor)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_serial_number)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_part_number)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_hardware_version)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_status)(unsigned int slot_index, char *buf, size_t count);
+ ssize_t (*get_slot_led_status)(unsigned int slot_index, char *buf, size_t count);
+ int (*set_slot_led_status)(unsigned int slot_index, int status);
+ ssize_t (*get_slot_power_status)(unsigned int slot_index, char *buf, size_t count);
+ int (*set_slot_power_status)(unsigned int slot_index, int status);
+ ssize_t (*get_slot_temp_alias)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_slot_temp_type)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_slot_temp_max)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_slot_temp_max)(unsigned int slot_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_slot_temp_min)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ int (*set_slot_temp_min)(unsigned int slot_index, unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_slot_temp_value)(unsigned int slot_index, unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_alias)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_type)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_max)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ int (*set_slot_vol_max)(unsigned int slot_index, unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_slot_vol_min)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ int (*set_slot_vol_min)(unsigned int slot_index, unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_slot_vol_range)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_nominal_value)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_vol_value)(unsigned int slot_index, unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_slot_curr_alias)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_slot_curr_type)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_slot_curr_max)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ int (*set_slot_curr_max)(unsigned int slot_index, unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_slot_curr_min)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ int (*set_slot_curr_min)(unsigned int slot_index, unsigned int curr_index, const char *buf, size_t count);
+ ssize_t (*get_slot_curr_value)(unsigned int slot_index, unsigned int curr_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_alias)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_type)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_firmware_version)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_board_version)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ ssize_t (*get_slot_fpga_test_reg)(unsigned int slot_index, unsigned int fpga_index, char *buf, size_t count);
+ int (*set_slot_fpga_test_reg)(unsigned int slot_index, unsigned int fpga_index, unsigned int value);
+ ssize_t (*get_slot_cpld_alias)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_type)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_firmware_version)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_board_version)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ ssize_t (*get_slot_cpld_test_reg)(unsigned int slot_index, unsigned int cpld_index, char *buf, size_t count);
+ int (*set_slot_cpld_test_reg)(unsigned int slot_index, unsigned int cpld_index, unsigned int value);
+};
+
+extern int s3ip_sysfs_slot_drivers_register(struct s3ip_sysfs_slot_drivers_s *drv);
+extern void s3ip_sysfs_slot_drivers_unregister(void);
+#endif /*_SLOT_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/switch.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/switch.h
new file mode 100644
index 000000000000..2f7e1ef2f8a1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/switch.h
@@ -0,0 +1,96 @@
+/*
+ * A header definition for switch driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SWITCH_H_
+#define _SWITCH_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "switch_driver.h"
+#include "wb_module.h"
+
+#define DIR_NAME_MAX_LEN (64)
+#define DEBUG_FILE_SIZE (64)
+#define DEV_PRESEN_STR "1\n"
+#define DEV_ABSENT_STR "0\n"
+#define mem_clear(data, size) memset((data), 0, (size))
+
+enum LOG_LEVEL {
+ INFO = 0x1,
+ ERR = 0x2,
+ DBG = 0x4,
+ ALL = 0xf
+};
+
+extern int g_switch_loglevel;
+
+#define check_pfun(p) do { \
+ if (p == NULL) { \
+ if (g_switch_loglevel & ERR) { \
+ printk(KERN_ERR "%s, %s is NULL.\n", __FUNCTION__, #p); \
+ } \
+ return -WB_SYSFS_RV_UNSUPPORT; \
+ } \
+} while (0)
+
+#define check_p(p) check_pfun(p)
+
+#define to_switch_obj(x) container_of(x, struct switch_obj, kobj)
+#define to_switch_attr(x) container_of(x, struct switch_attribute, attr)
+#define to_switch_device_attr(x) container_of(x, struct switch_device_attribute, switch_attr)
+
+#define SWITCH_ATTR(_name, _mode, _show, _store, _type) \
+ { .switch_attr = __ATTR(_name, _mode, _show, _store), \
+ .type = _type }
+
+#define SWITCH_DEVICE_ATTR(_name, _mode, _show, _store, _type) \
+struct switch_device_attribute switch_dev_attr_##_name \
+ = SWITCH_ATTR(_name, _mode, _show, _store, _type)
+
+struct switch_obj {
+ struct kobject kobj;
+ unsigned int index;
+};
+
+/* a custom attribute that works just for a struct switch_obj. */
+struct switch_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct switch_obj *foo, struct switch_attribute *attr, char *buf);
+ ssize_t (*store)(struct switch_obj *foo, struct switch_attribute *attr, const char *buf, size_t count);
+};
+
+struct switch_device_attribute {
+ struct switch_attribute switch_attr;
+ int type;
+};
+
+struct switch_obj *switch_kobject_create(const char *name, struct kobject *parent);
+void switch_kobject_delete(struct switch_obj **obj);
+int dev_debug_file_read(char *file_name, unsigned int dev_index, char *buf, int size);
+
+#endif /* _SWITCH_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/syseeprom_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/syseeprom_sysfs.h
new file mode 100644
index 000000000000..7ce272ad6112
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/syseeprom_sysfs.h
@@ -0,0 +1,32 @@
+/*
+ * A header definition for syseeprom_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SYSEEPROM_SYSFS_H_
+#define _SYSEEPROM_SYSFS_H_
+
+struct s3ip_sysfs_syseeprom_drivers_s {
+ int (*get_syseeprom_size)(void);
+ ssize_t (*read_syseeprom_data)(char *buf, loff_t offset, size_t count);
+ ssize_t (*write_syseeprom_data)(char *buf, loff_t offset, size_t count);
+};
+
+extern int s3ip_sysfs_syseeprom_drivers_register(struct s3ip_sysfs_syseeprom_drivers_s *drv);
+extern void s3ip_sysfs_syseeprom_drivers_unregister(void);
+#endif /*_SYSEEPROM_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/sysled_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/sysled_sysfs.h
new file mode 100644
index 000000000000..5eaf3af7057e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/sysled_sysfs.h
@@ -0,0 +1,39 @@
+/*
+ * A header definition for sysled_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SYSLED_SYSFS_H_
+#define _SYSLED_SYSFS_H_
+
+struct s3ip_sysfs_sysled_drivers_s {
+ ssize_t (*get_sys_led_status)(char *buf, size_t count);
+ int (*set_sys_led_status)(int status);
+ ssize_t (*get_bmc_led_status)(char *buf, size_t count);
+ int (*set_bmc_led_status)(int status);
+ ssize_t (*get_sys_fan_led_status)(char *buf, size_t count);
+ int (*set_sys_fan_led_status)(int status);
+ ssize_t (*get_sys_psu_led_status)(char *buf, size_t count);
+ int (*set_sys_psu_led_status)(int status);
+ ssize_t (*get_id_led_status)(char *buf, size_t count);
+ int (*set_id_led_status)(int status);
+};
+
+extern int s3ip_sysfs_sysled_drivers_register(struct s3ip_sysfs_sysled_drivers_s *drv);
+extern void s3ip_sysfs_sysled_drivers_unregister(void);
+#endif /*_SYSLED_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/system_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/system_sysfs.h
new file mode 100644
index 000000000000..a5edf5e107b8
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/system_sysfs.h
@@ -0,0 +1,54 @@
+/*
+ * A header definition for system_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SYSTEM_SYSFS_H_
+#define _SYSTEM_SYSFS_H_
+
+struct s3ip_sysfs_system_drivers_s {
+ ssize_t (*get_system_value)(unsigned int type, int *value, char *buf, size_t count);
+ ssize_t (*set_system_value)(unsigned int type, int value);
+ ssize_t (*get_system_port_power_status)(unsigned int type, char *buf, size_t count);
+};
+
+extern int s3ip_sysfs_system_drivers_register(struct s3ip_sysfs_system_drivers_s *drv);
+extern void s3ip_sysfs_system_drivers_unregister(void);
+
+/* system api type */
+typedef enum wb_plat_system_type_e {
+ WB_SYSTEM_BMC_READY = 0x0000, /* bmc ready */
+ WB_SYSTEM_SOL_ACTIVE = 0x0100, /* sol active */
+ WB_SYSTEM_PSU_RESET = 0x0200, /* psu reset */
+ WB_SYSTEM_CPU_BOARD_CTRL = 0x0300, /* cpu board control */
+ WB_SYSTEM_CPU_BOARD_STATUS = 0x0400, /* cpu board status */
+ WB_SYSTEM_BIOS_UPGRADE = 0x0500, /* bios upgrade */
+ WB_SYSTEM_BIOS_SWITCH = 0x0600, /* bios switch */
+ WB_SYSTEM_BIOS_VIEW = 0x0700, /* bios flash view */
+ WB_SYSTEM_BIOS_BOOT_OK = 0x0800, /* bios boot status */
+ WB_SYSTEM_BIOS_FAIL_RECORD = 0x0900, /* bios startup failure record */
+ WB_SYSTEM_BMC_RESET = 0x0a00, /* bmc reset */
+ WB_SYSTEM_MAC_BOARD_RESET = 0x0b00, /* mac board reset */
+ WB_SYSTEM_MAC_PWR_CTRL = 0x0c00, /* mac power on/off */
+ WB_SYSTEM_EMMC_PWR_CTRL = 0x0d00, /* emmc power on/off */
+ WB_SYSTEM_PORT_PWR_CTL = 0x0e00, /* power power on/off*/
+ WB_SYSTEM_BMC_VIEW = 0x0f00, /* bmc view */
+ WB_SYSTEM_BMC_SWITCH = 0x1000, /* bmc switch */
+} wb_plat_system_type_t;
+
+#endif /*_SYSTEM_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/temp_sensor_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/temp_sensor_sysfs.h
new file mode 100644
index 000000000000..dc6138388b34
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/temp_sensor_sysfs.h
@@ -0,0 +1,42 @@
+/*
+ * A header definition for temp_sensor_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _TEMP_SENSOR_SYSFS_H_
+#define _TEMP_SENSOR_SYSFS_H_
+
+struct s3ip_sysfs_temp_sensor_drivers_s {
+ int (*get_main_board_temp_number)(void);
+ ssize_t (*get_main_board_temp_alias)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_type)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_max)(unsigned int temp_index, char *buf, size_t count);
+ int (*set_main_board_temp_max)(unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_temp_min)(unsigned int temp_index, char *buf, size_t count);
+ int (*set_main_board_temp_min)(unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_temp_high)(unsigned int temp_index, char *buf, size_t count);
+ int (*set_main_board_temp_high)(unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_temp_low)(unsigned int temp_index, char *buf, size_t count);
+ int (*set_main_board_temp_low)(unsigned int temp_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_temp_value)(unsigned int temp_index, char *buf, size_t count);
+ ssize_t (*get_main_board_temp_monitor_flag)(unsigned int temp_index, char *buf, size_t count);
+};
+
+extern int s3ip_sysfs_temp_sensor_drivers_register(struct s3ip_sysfs_temp_sensor_drivers_s *drv);
+extern void s3ip_sysfs_temp_sensor_drivers_unregister(void);
+#endif /*_TEMP_SENSOR_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/transceiver_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/transceiver_sysfs.h
new file mode 100644
index 000000000000..a4fcb485d37a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/transceiver_sysfs.h
@@ -0,0 +1,50 @@
+/*
+ * A header definition for transceiver_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _TRANSCEIVER_SYSFS_H_
+#define _TRANSCEIVER_SYSFS_H_
+
+struct s3ip_sysfs_transceiver_drivers_s {
+ int (*get_eth_number)(void);
+ ssize_t (*get_transceiver_power_on_status)(char *buf, size_t count);
+ int (*set_transceiver_power_on_status)(int status);
+ ssize_t (*get_transceiver_present_status)(char *buf, size_t count);
+ ssize_t (*get_eth_power_on_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*set_eth_power_on_status)(unsigned int eth_index, int status);
+ ssize_t (*get_eth_tx_fault_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_tx_disable_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*set_eth_tx_disable_status)(unsigned int eth_index, int status);
+ ssize_t (*get_eth_present_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_rx_los_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_reset_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*set_eth_reset_status)(unsigned int eth_index, int status);
+ ssize_t (*get_eth_low_power_mode_status)(unsigned int eth_index, char *buf, size_t count);
+ ssize_t (*get_eth_interrupt_status)(unsigned int eth_index, char *buf, size_t count);
+ int (*get_eth_eeprom_size)(unsigned int eth_index);
+ ssize_t (*read_eth_eeprom_data)(unsigned int eth_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*write_eth_eeprom_data)(unsigned int eth_index, char *buf, loff_t offset, size_t count);
+ ssize_t (*get_eth_optoe_type)(unsigned int sff_index, int *optoe_type, char *buf, size_t count);
+ ssize_t (*set_eth_optoe_type)(unsigned int sff_index, int optoe_type);
+};
+
+extern int s3ip_sysfs_sff_drivers_register(struct s3ip_sysfs_transceiver_drivers_s *drv);
+extern void s3ip_sysfs_sff_drivers_unregister(void);
+#define SINGLE_TRANSCEIVER_PRESENT_DEBUG_FILE "/etc/sonic/.present_eth_%d"
+#endif /*_TRANSCEIVER_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/vol_sensor_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/vol_sensor_sysfs.h
new file mode 100644
index 000000000000..f13d4a2057e2
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/vol_sensor_sysfs.h
@@ -0,0 +1,40 @@
+/*
+ * A header definition for vol_sensor_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _VOL_SENSOR_SYSFS_H_
+#define _VOL_SENSOR_SYSFS_H_
+
+struct s3ip_sysfs_vol_sensor_drivers_s {
+ int (*get_main_board_vol_number)(void);
+ ssize_t (*get_main_board_vol_alias)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_type)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_max)(unsigned int vol_index, char *buf, size_t count);
+ int (*set_main_board_vol_max)(unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_vol_min)(unsigned int vol_index, char *buf, size_t count);
+ int (*set_main_board_vol_min)(unsigned int vol_index, const char *buf, size_t count);
+ ssize_t (*get_main_board_vol_range)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_nominal_value)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_value)(unsigned int vol_index, char *buf, size_t count);
+ ssize_t (*get_main_board_vol_monitor_flag)(unsigned int vol_index, char *buf, size_t count);
+};
+
+extern int s3ip_sysfs_vol_sensor_drivers_register(struct s3ip_sysfs_vol_sensor_drivers_s *drv);
+extern void s3ip_sysfs_vol_sensor_drivers_unregister(void);
+#endif /*_VOL_SENSOR_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/watchdog_sysfs.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/watchdog_sysfs.h
new file mode 100644
index 000000000000..ac9e7666aee8
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/include/watchdog_sysfs.h
@@ -0,0 +1,36 @@
+/*
+ * A header definition for watchdog_sysfs driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _WATCHDOG_SYSFS_H_
+#define _WATCHDOG_SYSFS_H_
+
+struct s3ip_sysfs_watchdog_drivers_s {
+ ssize_t (*get_watchdog_identify)(char *buf, size_t count);
+ ssize_t (*get_watchdog_timeleft)(char *buf, size_t count);
+ ssize_t (*get_watchdog_timeout)(char *buf, size_t count);
+ int (*set_watchdog_timeout)(int value);
+ ssize_t (*get_watchdog_enable_status)(char *buf, size_t count);
+ int (*set_watchdog_enable_status)(int value);
+ int (*set_watchdog_reset)(int value);
+};
+
+extern int s3ip_sysfs_watchdog_drivers_register(struct s3ip_sysfs_watchdog_drivers_s *drv);
+extern void s3ip_sysfs_watchdog_drivers_unregister(void);
+#endif /*_WATCHDOG_SYSFS_H_ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/psu_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/psu_sysfs.c
new file mode 100644
index 000000000000..ecb6ca30e6d4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/psu_sysfs.c
@@ -0,0 +1,1180 @@
+/*
+ * An psu_sysfs driver for psu sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "psu_sysfs.h"
+
+static int g_psu_loglevel = 0;
+static bool g_psu_present_debug = 0;
+
+#define PSU_INFO(fmt, args...) do { \
+ if (g_psu_loglevel & INFO) { \
+ printk(KERN_INFO "[PSU_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define PSU_ERR(fmt, args...) do { \
+ if (g_psu_loglevel & ERR) { \
+ printk(KERN_ERR "[PSU_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define PSU_DBG(fmt, args...) do { \
+ if (g_psu_loglevel & DBG) { \
+ printk(KERN_DEBUG "[PSU_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct temp_obj_s {
+ struct switch_obj *obj;
+};
+
+struct psu_obj_s {
+ unsigned int temp_number;
+ struct temp_obj_s *temp;
+ struct switch_obj *obj;
+ struct bin_attribute bin;
+ int psu_creat_bin_flag;
+};
+
+struct psu_s {
+ unsigned int psu_number;
+ struct psu_obj_s *psu;
+};
+
+static struct psu_s g_psu;
+static struct switch_obj *g_psu_obj = NULL;
+static struct s3ip_sysfs_psu_drivers_s *g_psu_drv = NULL;
+
+static ssize_t psu_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", g_psu.psu_number);
+}
+
+static ssize_t psu_temp_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int index;
+
+ index = obj->index;
+ PSU_DBG("psu index: %u\n",index);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_psu.psu[index - 1].temp_number);
+}
+
+static ssize_t psu_model_name_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_model_name);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_model_name(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_vendor_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_vendor);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_vendor(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_date_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_date);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_date(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_hw_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_hardware_version);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_hardware_version(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_sn_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_serial_number);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_serial_number(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_pn_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_part_number);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_part_number(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_type);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_type(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_in_curr_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_in_curr);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_in_curr(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_in_vol_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_in_vol);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_in_vol(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_in_power_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_in_power);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_in_power(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_out_curr_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_out_curr);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_out_curr(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_out_vol_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_out_vol);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_out_vol(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_out_power_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_out_power);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_out_power(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_out_max_power_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_out_max_power);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_out_max_power(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_present_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+ int ret, res;
+ char debug_file_buf[DEBUG_FILE_SIZE];
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_present_status);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ ret = g_psu_drv->get_psu_present_status(psu_index, buf, PAGE_SIZE);
+ if (ret < 0) {
+ PSU_ERR("get psu%u present status failed, ret: %d\n", psu_index, ret);
+ return ret;
+ }
+
+ if (g_psu_present_debug) {
+ PSU_INFO("s3ip sysfs psu present debug is enable\n");
+ if (strcmp(buf, DEV_ABSENT_STR) == 0) {
+ PSU_DBG("psu%d absent, return act value\n", psu_index);
+ return ret;
+ }
+
+ if ((strncmp(buf, SWITCH_DEV_NO_SUPPORT, strlen(SWITCH_DEV_NO_SUPPORT)) == 0) || (strncmp(buf, SWITCH_DEV_ERROR, strlen(SWITCH_DEV_ERROR)) == 0)) {
+ PSU_DBG("psu%d status sysfs unsupport or error\n", psu_index);
+ return ret;
+ }
+
+ mem_clear(debug_file_buf, sizeof(debug_file_buf));
+ res = dev_debug_file_read(SINGLE_PSU_PRESENT_DEBUG_FILE, psu_index, debug_file_buf, sizeof(debug_file_buf));
+ if (res) {
+ PSU_ERR("psu%u present debug file read failed, ret: %d\n", psu_index, res);
+ return ret;
+ }
+
+ if ((strcmp(debug_file_buf, DEV_PRESEN_STR) == 0) || (strcmp(debug_file_buf, DEV_ABSENT_STR) == 0)) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s", debug_file_buf);
+ } else {
+ PSU_ERR("psu%d present debug file value err, value: %s, not 0 or 1\n", psu_index, debug_file_buf);
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t get_psu_status_pmbus_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_status_pmbus);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_status_pmbus(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t get_psu_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_status);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_status(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t get_psu_hw_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_hw_status);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_hw_status(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t get_psu_alarm_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_alarm);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_alarm(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_out_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_out_status);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_out_status(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_in_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_in_status);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_in_status(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_fan_speed_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_fan_speed);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_fan_speed(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_fan_speed_cal_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_fan_speed_cal);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_fan_speed_cal(psu_index, buf, PAGE_SIZE);
+}
+
+ssize_t psu_fan_ratio_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_fan_ratio);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_fan_ratio(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_fan_ratio_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int psu_index;
+ int ret, ratio;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->set_psu_fan_ratio);
+
+ psu_index = obj->index;
+ ret = kstrtoint(buf, 0, &ratio);
+ if (ret != 0) {
+ PSU_ERR("invaild psu fan ratio ret: %d, buf: %s.\n", ret, buf);
+ return -EINVAL;
+ }
+ if (ratio < 0 || ratio > 100) {
+ PSU_ERR("param invalid, can not set ratio: %d.\n", ratio);
+ return -EINVAL;
+ }
+ PSU_DBG("psu index: %u, ratio: %d\n", psu_index, ratio);
+ ret = g_psu_drv->set_psu_fan_ratio(psu_index, ratio);
+ if (ret < 0) {
+ PSU_ERR("set psu%u ratio: %d failed, ret: %d\n",
+ psu_index, ratio, ret);
+ return ret;
+ }
+ PSU_DBG("set psu%u, ratio: %d success\n", psu_index, ratio);
+ return count;
+}
+
+static ssize_t psu_fan_direction_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_fan_direction);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_fan_direction(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_led_status);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_led_status(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_temp_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_temp_value);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ psu_index = p_obj->index;
+ temp_index = obj->index;
+
+ PSU_DBG("psu index: %u, temp index: %u\n", psu_index, temp_index);
+ return g_psu_drv->get_psu_temp_value(psu_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_temp_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_temp_alias);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ psu_index = p_obj->index;
+ temp_index = obj->index;
+
+ PSU_DBG("psu index: %u, temp index: %u\n", psu_index, temp_index);
+ return g_psu_drv->get_psu_temp_alias(psu_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_temp_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_temp_type);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ psu_index = p_obj->index;
+ temp_index = obj->index;
+
+ PSU_DBG("psu index: %u, temp index: %u\n", psu_index, temp_index);
+ return g_psu_drv->get_psu_temp_type(psu_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_temp_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_temp_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ psu_index = p_obj->index;
+ temp_index = obj->index;
+
+ PSU_DBG("psu index: %u, temp index: %u\n", psu_index, temp_index);
+ return g_psu_drv->get_psu_temp_max(psu_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_temp_max_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int psu_index, temp_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->set_psu_temp_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ psu_index = p_obj->index;
+ temp_index = obj->index;
+ ret = g_psu_drv->set_psu_temp_max(psu_index, temp_index, buf, count);
+ if (ret < 0) {
+ PSU_ERR("set psu%u temp%u max threshold failed, value: %s, count: %lu, ret: %d\n",
+ psu_index, temp_index, buf, count, ret);
+ return ret;
+ }
+ PSU_DBG("set psu%u temp%u max threshold success, value: %s, count: %lu, ret: %d\n",
+ psu_index, temp_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t psu_temp_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_temp_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ psu_index = p_obj->index;
+ temp_index = obj->index;
+
+ PSU_DBG("psu index: %u, temp index: %u\n", psu_index, temp_index);
+ return g_psu_drv->get_psu_temp_min(psu_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_temp_min_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int psu_index, temp_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->set_psu_temp_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ psu_index = p_obj->index;
+ temp_index = obj->index;
+ ret = g_psu_drv->set_psu_temp_min(psu_index, temp_index, buf, count);
+ if (ret < 0) {
+ PSU_ERR("set psu%u temp%u min threshold failed, value: %s, count: %lu, ret: %d\n",
+ psu_index, temp_index, buf, count, ret);
+ return ret;
+ }
+ PSU_DBG("set psu%u temp%u min threshold success, value: %s, count: %lu, ret: %d\n",
+ psu_index, temp_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t psu_attr_threshold_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int psu_index;
+ struct switch_device_attribute *tmp_attr;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_attr_threshold);
+
+ psu_index = obj->index;
+ tmp_attr = to_switch_device_attr(attr);
+ check_p(tmp_attr);
+ return g_psu_drv->get_psu_attr_threshold(psu_index, tmp_attr->type, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_eeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t count)
+{
+ struct switch_obj *psu_obj;
+ ssize_t rd_len;
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->read_psu_eeprom_data);
+
+ psu_obj = to_switch_obj(kobj);
+ psu_index = psu_obj->index;
+ mem_clear(buf, count);
+ rd_len = g_psu_drv->read_psu_eeprom_data(psu_index, buf, offset, count);
+ if (rd_len < 0) {
+ PSU_ERR("read psu%u eeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
+ psu_index, offset, count, rd_len);
+ return rd_len;
+ }
+
+ PSU_DBG("read psu%u eeprom data success, offset:0x%llx, read len:%lu, really read len:%ld.\n",
+ psu_index, offset, count, rd_len);
+
+ return rd_len;
+}
+
+static ssize_t psu_blackbox_info_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_blackbox_info);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_blackbox_info(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_pmbus_info_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int psu_index;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->get_psu_pmbus_info);
+
+ psu_index = obj->index;
+ PSU_DBG("psu index: %u\n", psu_index);
+ return g_psu_drv->get_psu_pmbus_info(psu_index, buf, PAGE_SIZE);
+}
+
+static ssize_t psu_clear_blackbox_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int psu_index;
+ int ret;
+ uint8_t vaule;
+
+ check_p(g_psu_drv);
+ check_p(g_psu_drv->clear_psu_blackbox);
+
+ psu_index = obj->index;
+ ret = kstrtou8(buf, 0, &vaule);
+ if (ret != 0) {
+ PSU_ERR("Invaild value ret: %d, buf: %s.\n", ret, buf);
+ return -EINVAL;
+ }
+ if (vaule != 1) {
+ PSU_ERR("Invaild value: %u, only support write 1 to clear psu blackbox information\n", vaule);
+ return -EINVAL;
+ }
+ PSU_DBG("psu index: %u, clear psu blackbox information\n", psu_index);
+ ret = g_psu_drv->clear_psu_blackbox(psu_index, vaule);
+ if (ret < 0) {
+ PSU_ERR("clear psu%u blackbox information failed, ret: %d\n",
+ psu_index, ret);
+ return ret;
+ }
+ PSU_DBG("clear psu%u blackbox information success\n", psu_index);
+ return count;
+}
+
+/************************************psu dir and attrs*******************************************/
+static struct switch_attribute psu_number_att = __ATTR(number, S_IRUGO, psu_number_show, NULL);
+
+static struct attribute *psu_dir_attrs[] = {
+ &psu_number_att.attr,
+ NULL,
+};
+
+static struct attribute_group psu_root_attr_group = {
+ .attrs = psu_dir_attrs,
+};
+
+/*******************************psu[1-n] dir and attrs*******************************************/
+static struct switch_attribute psu_model_name_attr = __ATTR(model_name, S_IRUGO, psu_model_name_show, NULL);
+static struct switch_attribute psu_vendor_attr = __ATTR(vendor, S_IRUGO, psu_vendor_show, NULL);
+static struct switch_attribute psu_date_attr = __ATTR(date, S_IRUGO, psu_date_show, NULL);
+static struct switch_attribute psu_hw_attr = __ATTR(hardware_version, S_IRUGO, psu_hw_show, NULL);
+static struct switch_attribute psu_sn_attr = __ATTR(serial_number, S_IRUGO, psu_sn_show, NULL);
+static struct switch_attribute psu_pn_attr = __ATTR(part_number, S_IRUGO, psu_pn_show, NULL);
+static struct switch_attribute psu_type_attr = __ATTR(type, S_IRUGO, psu_type_show, NULL);
+static struct switch_attribute psu_in_curr_attr = __ATTR(in_curr, S_IRUGO, psu_in_curr_show, NULL);
+static struct switch_attribute psu_in_vol_attr = __ATTR(in_vol, S_IRUGO, psu_in_vol_show, NULL);
+static struct switch_attribute psu_in_power_attr = __ATTR(in_power, S_IRUGO, psu_in_power_show, NULL);
+static struct switch_attribute psu_out_curr_attr = __ATTR(out_curr, S_IRUGO, psu_out_curr_show, NULL);
+static struct switch_attribute psu_out_vol_attr = __ATTR(out_vol, S_IRUGO, psu_out_vol_show, NULL);
+static struct switch_attribute psu_out_power_attr = __ATTR(out_power, S_IRUGO, psu_out_power_show, NULL);
+static struct switch_attribute psu_out_max_power_attr = __ATTR(out_max_power, S_IRUGO, psu_out_max_power_show, NULL);
+static struct switch_attribute psu_num_temps_attr = __ATTR(num_temp_sensors, S_IRUGO, psu_temp_number_show, NULL);
+static struct switch_attribute psu_present_attr = __ATTR(present, S_IRUGO, psu_present_status_show, NULL);
+static struct switch_attribute status_fr_pmbus_attr = __ATTR(status_fr_pmbus, S_IRUGO, get_psu_status_pmbus_show, NULL);
+static struct switch_attribute psu_status_attr = __ATTR(status, S_IRUGO, get_psu_status_show, NULL);
+static struct switch_attribute psu_hw_status_attr = __ATTR(hw_status, S_IRUGO, get_psu_hw_status_show, NULL);
+static struct switch_attribute psu_alarm_attr = __ATTR(alarm, S_IRUGO, get_psu_alarm_show, NULL);
+static struct switch_attribute psu_out_status_attr = __ATTR(out_status, S_IRUGO, psu_out_status_show, NULL);
+static struct switch_attribute psu_in_status_attr = __ATTR(in_status, S_IRUGO, psu_in_status_show, NULL);
+static struct switch_attribute psu_fan_speed_attr = __ATTR(fan_speed, S_IRUGO, psu_fan_speed_show, NULL);
+static struct switch_attribute psu_fan_ratio_attr = __ATTR(fan_ratio, S_IRUGO | S_IWUSR, psu_fan_ratio_show, psu_fan_ratio_store);
+static struct switch_attribute psu_fan_direction_attr = __ATTR(fan_direction, S_IRUGO, psu_fan_direction_show, NULL);
+static struct switch_attribute psu_led_status_attr = __ATTR(led_status, S_IRUGO, psu_led_status_show, NULL);
+static struct switch_attribute psu_fan_speed_cal_attr = __ATTR(fan_speed_cal, S_IRUGO, psu_fan_speed_cal_show, NULL);
+static struct switch_attribute psu_blackbox_info_attr = __ATTR(blackbox_info, S_IRUGO, psu_blackbox_info_show, NULL);
+static struct switch_attribute psu_pmbus_info_attr = __ATTR(pmbus_info, S_IRUGO, psu_pmbus_info_show, NULL);
+static struct switch_attribute psu_clear_blackbox_attr = __ATTR(clear_blackbox, S_IWUSR, NULL, psu_clear_blackbox_store);
+static SWITCH_DEVICE_ATTR(in_vol_max, S_IRUGO, psu_attr_threshold_show, NULL, PSU_IN_VOL_MAX);
+static SWITCH_DEVICE_ATTR(in_vol_min, S_IRUGO, psu_attr_threshold_show, NULL, PSU_IN_VOL_MIN);
+static SWITCH_DEVICE_ATTR(in_curr_max, S_IRUGO, psu_attr_threshold_show, NULL, PSU_IN_CURR_MAX);
+static SWITCH_DEVICE_ATTR(in_curr_min, S_IRUGO, psu_attr_threshold_show, NULL, PSU_IN_CURR_MIN);
+static SWITCH_DEVICE_ATTR(in_power_max, S_IRUGO, psu_attr_threshold_show, NULL, PSU_IN_POWER_MAX);
+static SWITCH_DEVICE_ATTR(in_power_min, S_IRUGO, psu_attr_threshold_show, NULL, PSU_IN_POWER_MIN);
+static SWITCH_DEVICE_ATTR(out_vol_max, S_IRUGO, psu_attr_threshold_show, NULL, PSU_OUT_VOL_MAX);
+static SWITCH_DEVICE_ATTR(out_vol_min, S_IRUGO, psu_attr_threshold_show, NULL, PSU_OUT_VOL_MIN);
+static SWITCH_DEVICE_ATTR(out_curr_max, S_IRUGO, psu_attr_threshold_show, NULL, PSU_OUT_CURR_MAX);
+static SWITCH_DEVICE_ATTR(out_curr_min, S_IRUGO, psu_attr_threshold_show, NULL, PSU_OUT_CURR_MIN);
+static SWITCH_DEVICE_ATTR(out_power_max, S_IRUGO, psu_attr_threshold_show, NULL, PSU_OUT_POWER_MAX);
+static SWITCH_DEVICE_ATTR(out_power_min, S_IRUGO, psu_attr_threshold_show, NULL, PSU_OUT_POWER_MIN);
+static SWITCH_DEVICE_ATTR(fan_speed_max, S_IRUGO, psu_attr_threshold_show, NULL, PSU_FAN_SPEED_MAX);
+static SWITCH_DEVICE_ATTR(fan_speed_min, S_IRUGO, psu_attr_threshold_show, NULL, PSU_FAN_SPEED_MIN);
+
+static struct attribute *psu_attrs[] = {
+ &psu_model_name_attr.attr,
+ &psu_vendor_attr.attr,
+ &psu_date_attr.attr,
+ &psu_hw_attr.attr,
+ &psu_sn_attr.attr,
+ &psu_pn_attr.attr,
+ &psu_type_attr.attr,
+ &psu_in_curr_attr.attr,
+ &psu_in_vol_attr.attr,
+ &psu_in_power_attr.attr,
+ &psu_out_curr_attr.attr,
+ &psu_out_vol_attr.attr,
+ &psu_out_power_attr.attr,
+ &psu_out_max_power_attr.attr,
+ &psu_num_temps_attr.attr,
+ &psu_present_attr.attr,
+ &status_fr_pmbus_attr.attr,
+ &psu_status_attr.attr,
+ &psu_hw_status_attr.attr,
+ &psu_alarm_attr.attr,
+ &psu_out_status_attr.attr,
+ &psu_in_status_attr.attr,
+ &psu_fan_speed_attr.attr,
+ &psu_fan_ratio_attr.attr,
+ &psu_fan_direction_attr.attr,
+ &psu_led_status_attr.attr,
+ &psu_fan_speed_cal_attr.attr,
+ &psu_blackbox_info_attr.attr,
+ &psu_pmbus_info_attr.attr,
+ &psu_clear_blackbox_attr.attr,
+ &switch_dev_attr_in_vol_max.switch_attr.attr,
+ &switch_dev_attr_in_vol_min.switch_attr.attr,
+ &switch_dev_attr_in_curr_max.switch_attr.attr,
+ &switch_dev_attr_in_curr_min.switch_attr.attr,
+ &switch_dev_attr_in_power_max.switch_attr.attr,
+ &switch_dev_attr_in_power_min.switch_attr.attr,
+ &switch_dev_attr_out_vol_max.switch_attr.attr,
+ &switch_dev_attr_out_vol_min.switch_attr.attr,
+ &switch_dev_attr_out_curr_max.switch_attr.attr,
+ &switch_dev_attr_out_curr_min.switch_attr.attr,
+ &switch_dev_attr_out_power_max.switch_attr.attr,
+ &switch_dev_attr_out_power_min.switch_attr.attr,
+ &switch_dev_attr_fan_speed_max.switch_attr.attr,
+ &switch_dev_attr_fan_speed_min.switch_attr.attr,
+ NULL,
+};
+
+static struct attribute_group psu_attr_group = {
+ .attrs = psu_attrs,
+};
+
+/*******************************psu temp[1-n] dir and attrs*******************************************/
+static struct switch_attribute psu_temp_alias_attr = __ATTR(alias, S_IRUGO, psu_temp_alias_show, NULL);
+static struct switch_attribute psu_temp_type_attr = __ATTR(type, S_IRUGO, psu_temp_type_show, NULL);
+static struct switch_attribute psu_temp_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, psu_temp_max_show, psu_temp_max_store);
+static struct switch_attribute psu_temp_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, psu_temp_min_show, psu_temp_min_store);
+static struct switch_attribute psu_temp_value_attr = __ATTR(value, S_IRUGO, psu_temp_value_show, NULL);
+
+static struct attribute *psu_temp_attrs[] = {
+ &psu_temp_alias_attr.attr,
+ &psu_temp_type_attr.attr,
+ &psu_temp_max_attr.attr,
+ &psu_temp_min_attr.attr,
+ &psu_temp_value_attr.attr,
+ NULL,
+};
+
+static struct attribute_group psu_temp_attr_group = {
+ .attrs = psu_temp_attrs,
+};
+
+static void psuindex_single_temp_remove_kobj_and_attrs(struct psu_obj_s *curr_psu, unsigned int temp_index)
+{
+ struct temp_obj_s *curr_temp; /* point to temp1 temp2...*/
+
+ curr_temp = &curr_psu->temp[temp_index - 1];
+ if (curr_temp->obj) {
+ sysfs_remove_group(&curr_temp->obj->kobj, &psu_temp_attr_group);
+ switch_kobject_delete(&curr_temp->obj);
+ PSU_DBG("delete psu%u temp%u dir and attrs success.\n", curr_psu->obj->index, temp_index);
+ }
+ return;
+}
+
+static int psuindex_single_temp_create_kobj_and_attrs(struct psu_obj_s *curr_psu, unsigned int temp_index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct temp_obj_s *curr_temp; /* point to temp1 temp2...*/
+
+ curr_temp = &curr_psu->temp[temp_index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "temp%u", temp_index);
+ curr_temp->obj = switch_kobject_create(name, &curr_psu->obj->kobj);
+ if (!curr_temp->obj) {
+ PSU_ERR("create psu%u, %s object error!\n", curr_psu->obj->index, name);
+ return -ENOMEM;
+ }
+ curr_temp->obj->index = temp_index;
+ if (sysfs_create_group(&curr_temp->obj->kobj, &psu_temp_attr_group) != 0) {
+ PSU_ERR("create psu%u, %s attrs error.\n", curr_psu->obj->index, name);
+ switch_kobject_delete(&curr_temp->obj);
+ return -EBADRQC;
+ }
+ PSU_DBG("create psu%u, %s success.\n", curr_psu->obj->index, name);
+ return 0;
+}
+
+static int psuindex_temp_create_kobj_and_attrs(struct psu_obj_s *curr_psu)
+{
+ unsigned int temp_index, i, temp_num;
+
+ temp_num = curr_psu->temp_number;
+ curr_psu->temp = kzalloc(sizeof(struct temp_obj_s) * temp_num, GFP_KERNEL);
+ if (!curr_psu->temp) {
+ PSU_ERR("kzalloc temp error, psu index: %u, temp number: %u.\n",
+ curr_psu->obj->index, temp_num);
+ return -ENOMEM;
+ }
+ for(temp_index = 1; temp_index <= temp_num; temp_index++) {
+ if(psuindex_single_temp_create_kobj_and_attrs(curr_psu, temp_index) != 0 ) {
+ goto temp_error;
+ }
+ }
+ return 0;
+temp_error:
+ for(i = temp_index; i > 0; i--) {
+ psuindex_single_temp_remove_kobj_and_attrs(curr_psu, i);
+ }
+ kfree(curr_psu->temp);
+ curr_psu->temp = NULL;
+ return -EBADRQC;
+}
+
+static void psuindex_temp_remove_kobj_and_attrs(struct psu_obj_s *curr_psu)
+{
+ unsigned int temp_index, temp_num;
+
+ if (curr_psu->temp) {
+ temp_num = curr_psu->temp_number;
+ for (temp_index = temp_num; temp_index > 0; temp_index--) {
+ psuindex_single_temp_remove_kobj_and_attrs(curr_psu, temp_index);
+ }
+ kfree(curr_psu->temp);
+ curr_psu->temp = NULL;
+ }
+ return;
+}
+
+/* create psu temp[1-n] directory and attributes*/
+static int psu_temp_create(void)
+{
+ int psu_num, temp_num;
+ unsigned int psu_index, i;
+ struct psu_obj_s *curr_psu; /* point to psu1 psu2...*/
+
+ psu_num = g_psu.psu_number;
+ if (psu_num <= 0) {
+ PSU_DBG("psu number: %d, skip to create temp* dirs and attrs.\n", psu_num);
+ return 0;
+ }
+
+ check_p(g_psu_drv->get_psu_temp_number);
+ for(psu_index = 1; psu_index <= psu_num; psu_index++) {
+ temp_num = g_psu_drv->get_psu_temp_number(psu_index);
+ if (temp_num <= 0) {
+ PSU_DBG("psu%u temp number: %d, don't need to create temp* dirs and attrs.\n",
+ psu_index, temp_num);
+ continue;
+ }
+ curr_psu = &g_psu.psu[psu_index - 1];
+ curr_psu->temp_number = temp_num;
+ if(psuindex_temp_create_kobj_and_attrs(curr_psu) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for(i = psu_index; i > 0; i--) {
+ curr_psu = &g_psu.psu[i - 1];
+ psuindex_temp_remove_kobj_and_attrs(curr_psu);
+ }
+ return -EBADRQC;
+}
+
+/* delete psu temp[1-n] directory and attributes*/
+static void psu_temp_remove(void)
+{
+ unsigned int psu_index;
+ struct psu_obj_s *curr_psu;
+
+ if (g_psu.psu) {
+ for(psu_index = g_psu.psu_number; psu_index > 0; psu_index--) {
+ curr_psu = &g_psu.psu[psu_index - 1];
+ psuindex_temp_remove_kobj_and_attrs(curr_psu);
+ curr_psu->temp_number = 0;
+ }
+ }
+ return;
+}
+
+/* create psu* eeprom attributes */
+static int psu_sub_single_create_eeprom_attrs(unsigned int index)
+{
+ int ret, eeprom_size;
+ struct psu_obj_s *curr_psu;
+
+ check_p(g_psu_drv->get_psu_eeprom_size);
+ eeprom_size = g_psu_drv->get_psu_eeprom_size(index);
+ if (eeprom_size <= 0) {
+ PSU_INFO("psu%u, eeprom_size: %d, don't need to creat eeprom attr.\n",
+ index, eeprom_size);
+ return 0;
+ }
+
+ curr_psu = &g_psu.psu[index - 1];
+ sysfs_bin_attr_init(&curr_psu->bin);
+ curr_psu->bin.attr.name = "eeprom";
+ curr_psu->bin.attr.mode = 0444;
+ curr_psu->bin.read = psu_eeprom_read;
+ curr_psu->bin.size = eeprom_size;
+
+ ret = sysfs_create_bin_file(&curr_psu->obj->kobj, &curr_psu->bin);
+ if (ret) {
+ PSU_ERR("psu%u, create eeprom bin error, ret: %d. \n", index, ret);
+ return -EBADRQC;
+ }
+
+ PSU_DBG("psu%u, create bin file success, eeprom size:%d.\n", index, eeprom_size);
+ curr_psu->psu_creat_bin_flag = 1;
+ return 0;
+}
+
+static int psu_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct psu_obj_s *curr_psu;
+
+ curr_psu = &g_psu.psu[index - 1];
+ if (curr_psu->obj) {
+ if (curr_psu->psu_creat_bin_flag) {
+ sysfs_remove_bin_file(&curr_psu->obj->kobj, &curr_psu->bin);
+ curr_psu->psu_creat_bin_flag = 0;
+ }
+ sysfs_remove_group(&curr_psu->obj->kobj, &psu_attr_group);
+ switch_kobject_delete(&curr_psu->obj);
+ PSU_DBG("delete psu%u dir and attrs success.\n", index);
+ }
+ return 0;
+}
+
+static int psu_sub_single_create_kobj(struct kobject *parent, unsigned int index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct psu_obj_s *curr_psu;
+
+ curr_psu = &g_psu.psu[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "psu%u", index);
+ curr_psu->obj = switch_kobject_create(name, parent);
+ if (!curr_psu->obj) {
+ PSU_ERR("create %s object error!\n", name);
+ return -ENOMEM;
+ }
+ curr_psu->obj->index = index;
+ if (sysfs_create_group(&curr_psu->obj->kobj, &psu_attr_group) != 0) {
+ PSU_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&curr_psu->obj);
+ return -EBADRQC;
+ }
+ PSU_DBG("create %s dir and attrs success.\n", name);
+ return 0;
+}
+
+
+static int psu_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ int ret;
+
+ ret = psu_sub_single_create_kobj(parent, index);
+ if (ret < 0) {
+ PSU_ERR("create psu%d dir error.\n", index);
+ return ret;
+ }
+
+ psu_sub_single_create_eeprom_attrs(index);
+ return 0;
+}
+
+static int psu_sub_create_kobj_and_attrs(struct kobject *parent, int psu_num)
+{
+ unsigned int psu_index, i;
+
+ g_psu.psu = kzalloc(sizeof(struct psu_obj_s) * psu_num, GFP_KERNEL);
+ if (!g_psu.psu) {
+ PSU_ERR("kzalloc psu.psu error, psu number = %d.\n", psu_num);
+ return -ENOMEM;
+ }
+
+ for (psu_index = 1; psu_index <= psu_num; psu_index++) {
+ if (psu_sub_single_create_kobj_and_attrs(parent, psu_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = psu_index; i > 0; i--) {
+ psu_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_psu.psu);
+ g_psu.psu = NULL;
+ return -EBADRQC;
+}
+
+/* create psu[1-n] directory and attributes*/
+static int psu_sub_create(void)
+{
+ int ret;
+
+ ret = psu_sub_create_kobj_and_attrs(&g_psu_obj->kobj, g_psu.psu_number);
+ return ret;
+}
+
+/* delete psu[1-n] directory and attributes*/
+static void psu_sub_remove(void)
+{
+ unsigned int psu_index;
+
+ if (g_psu.psu) {
+ for (psu_index = g_psu.psu_number; psu_index > 0; psu_index--) {
+ psu_sub_single_remove_kobj_and_attrs(psu_index);
+ }
+ kfree(g_psu.psu);
+ g_psu.psu = NULL;
+ }
+ g_psu.psu_number = 0;
+ return;
+}
+
+/* create psu directory and number attributes*/
+static int psu_root_create(void)
+{
+ g_psu_obj = switch_kobject_create("psu", NULL);
+ if (!g_psu_obj) {
+ PSU_ERR("switch_kobject_create psu error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_psu_obj->kobj, &psu_root_attr_group) != 0) {
+ switch_kobject_delete(&g_psu_obj);
+ PSU_ERR("create psu dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete psu directory and number attributes*/
+static void psu_root_remove(void)
+{
+ if (g_psu_obj) {
+ sysfs_remove_group(&g_psu_obj->kobj, &psu_root_attr_group);
+ switch_kobject_delete(&g_psu_obj);
+ PSU_DBG("delete psu dir and attrs success.\n");
+ }
+ return;
+}
+
+int s3ip_sysfs_psu_drivers_register(struct s3ip_sysfs_psu_drivers_s *drv)
+{
+ int ret, psu_num;
+
+ PSU_INFO("s3ip_sysfs_psu_drivers_register...\n");
+ if (g_psu_drv) {
+ PSU_ERR("g_psu_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_psu_number);
+ g_psu_drv = drv;
+
+ psu_num = g_psu_drv->get_psu_number();
+ if (psu_num <= 0) {
+ PSU_ERR("psu number: %d, don't need to create psu dirs and attrs.\n", psu_num);
+ g_psu_drv = NULL;
+ return -EINVAL;
+ }
+
+ mem_clear(&g_psu, sizeof(struct psu_s));
+ g_psu.psu_number = psu_num;
+ ret = psu_root_create();
+ if (ret < 0) {
+ PSU_ERR("create psu root dir and attrs failed, ret: %d\n", ret);
+ g_psu_drv = NULL;
+ return ret;
+ }
+
+ ret = psu_sub_create();
+ if (ret < 0) {
+ PSU_ERR("create psu sub dir and attrs failed, ret: %d\n", ret);
+ psu_root_remove();
+ g_psu_drv = NULL;
+ return ret;
+ }
+
+ ret = psu_temp_create();
+ if (ret < 0) {
+ PSU_ERR("create psu temp dir and attrs failed, ret: %d\n", ret);
+ psu_sub_remove();
+ psu_root_remove();
+ g_psu_drv = NULL;
+ return ret;
+ }
+ PSU_INFO("s3ip_sysfs_psu_drivers_register success.\n");
+ return 0;
+}
+
+void s3ip_sysfs_psu_drivers_unregister(void)
+{
+ if (g_psu_drv) {
+ psu_temp_remove();
+ psu_sub_remove();
+ psu_root_remove();
+ g_psu_drv = NULL;
+ PSU_DBG("s3ip_sysfs_psu_drivers_unregister success.\n");
+ }
+
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_psu_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_psu_drivers_unregister);
+module_param(g_psu_loglevel, int, 0644);
+MODULE_PARM_DESC(g_psu_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
+module_param(g_psu_present_debug, bool, 0644);
+MODULE_PARM_DESC(g_psu_present_debug, "the psu present debug switch(0: disable, 1:enable, defalut: 0).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/slot_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/slot_sysfs.c
new file mode 100644
index 000000000000..eb3bde77b7dd
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/slot_sysfs.c
@@ -0,0 +1,1955 @@
+/*
+ * An slot_sysfs driver for slot sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "slot_sysfs.h"
+
+static int g_slot_loglevel = 0;
+
+#define SLOT_INFO(fmt, args...) do { \
+ if (g_slot_loglevel & INFO) { \
+ printk(KERN_INFO "[SLOT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SLOT_ERR(fmt, args...) do { \
+ if (g_slot_loglevel & ERR) { \
+ printk(KERN_ERR "[SLOT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SLOT_DBG(fmt, args...) do { \
+ if (g_slot_loglevel & DBG) { \
+ printk(KERN_DEBUG "[SLOT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct slot_temp_obj_s {
+ struct switch_obj *obj;
+};
+
+struct slot_vol_obj_s {
+ struct switch_obj *obj;
+};
+
+struct slot_curr_obj_s {
+ struct switch_obj *obj;
+};
+
+struct slot_fpga_obj_s {
+ struct switch_obj *obj;
+};
+
+struct slot_cpld_obj_s {
+ struct switch_obj *obj;
+};
+
+struct slot_obj_s {
+ unsigned int temp_number;
+ unsigned int vol_number;
+ unsigned int curr_number;
+ unsigned int fpga_number;
+ unsigned int cpld_number;
+ struct slot_temp_obj_s *temp;
+ struct slot_vol_obj_s *vol;
+ struct slot_curr_obj_s *curr;
+ struct slot_fpga_obj_s *fpga;
+ struct slot_cpld_obj_s *cpld;
+ struct switch_obj *obj;
+};
+
+struct slot_s {
+ unsigned int slot_number;
+ struct slot_obj_s *slot;
+};
+
+static struct slot_s g_slot;
+static struct switch_obj *g_slot_obj = NULL;
+static struct s3ip_sysfs_slot_drivers_s *g_slot_drv = NULL;
+
+static ssize_t slot_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_slot.slot_number);
+}
+
+static ssize_t slot_temp_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int index;
+
+ index = obj->index;
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_slot.slot[index - 1].temp_number);
+}
+
+static ssize_t slot_vol_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int index;
+
+ index = obj->index;
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_slot.slot[index - 1].vol_number);
+}
+
+static ssize_t slot_curr_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int index;
+
+ index = obj->index;
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_slot.slot[index - 1].curr_number);
+}
+
+static ssize_t slot_fpga_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int index;
+
+ index = obj->index;
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_slot.slot[index - 1].fpga_number);
+}
+
+static ssize_t slot_cpld_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int index;
+
+ index = obj->index;
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_slot.slot[index - 1].cpld_number);
+}
+
+static ssize_t slot_model_name_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_model_name);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_model_name(slot_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_vendor_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vendor);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_vendor(slot_index, buf, PAGE_SIZE);
+}
+static ssize_t slot_sn_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_serial_number);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_serial_number(slot_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_pn_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_part_number);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_part_number(slot_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_hw_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_hardware_version);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_hardware_version(slot_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_status);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_status(slot_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_led_status_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_led_status);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_led_status(slot_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_led_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int slot_index;
+ int ret, led_status;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_led_status);
+
+ slot_index = obj->index;
+ ret = kstrtoint(buf, 0, &led_status);
+ if (ret != 0) {
+ SLOT_ERR("invaild slot led status ret: %d, buf: %s.\n", ret, buf);
+ return -EINVAL;
+ }
+ SLOT_DBG("slot index: %u, led_status: %d\n", slot_index, led_status);
+ ret = g_slot_drv->set_slot_led_status(slot_index, led_status);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u led_status: %d failed, ret: %d\n", slot_index, led_status, ret);
+ return -EIO;
+ }
+ SLOT_DBG("set slot%u led_status: %d success\n", slot_index, led_status);
+ return count;
+}
+
+/*************************************slot temp*************************************************/
+static ssize_t slot_temp_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_temp_value);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ temp_index = obj->index;
+
+ SLOT_DBG("slot index: %u, temp index: %u\n", slot_index, temp_index);
+ return g_slot_drv->get_slot_temp_value(slot_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_temp_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_temp_alias);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ temp_index = obj->index;
+
+ SLOT_DBG("slot index: %u, temp index: %u\n", slot_index, temp_index);
+ return g_slot_drv->get_slot_temp_alias(slot_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_temp_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_temp_type);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ temp_index = obj->index;
+
+ SLOT_DBG("slot index: %u, temp index: %u\n", slot_index, temp_index);
+ return g_slot_drv->get_slot_temp_type(slot_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_temp_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_temp_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ temp_index = obj->index;
+
+ SLOT_DBG("slot index: %u, temp index: %u\n", slot_index, temp_index);
+ return g_slot_drv->get_slot_temp_max(slot_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_temp_max_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, temp_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_temp_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ temp_index = obj->index;
+ ret = g_slot_drv->set_slot_temp_max(slot_index, temp_index, buf, count);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u temp%u max threshold failed, value: %s, count: %lu, ret: %d\n",
+ slot_index, temp_index, buf, count, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u temp%u max threshold success, value: %s, count: %lu, ret: %d\n",
+ slot_index, temp_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t slot_temp_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, temp_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_temp_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ temp_index = obj->index;
+
+ SLOT_DBG("slot index: %u, temp index: %u\n", slot_index, temp_index);
+ return g_slot_drv->get_slot_temp_min(slot_index, temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_temp_min_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, temp_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_temp_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ temp_index = obj->index;
+ ret = g_slot_drv->set_slot_temp_min(slot_index, temp_index, buf, count);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u temp%u min threshold failed, value: %s, count: %lu, ret: %d\n",
+ slot_index, temp_index, buf, count, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u temp%u min threshold success, value: %s, count: %lu, ret: %d\n",
+ slot_index, temp_index, buf, count, ret);
+ return count;
+}
+/**********************************end of slot temp**********************************************/
+
+/*************************************slot vol*************************************************/
+static ssize_t slot_vol_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, vol_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vol_value);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+
+ SLOT_DBG("slot index: %u, vol index: %u\n", slot_index, vol_index);
+ return g_slot_drv->get_slot_vol_value(slot_index, vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_vol_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, vol_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vol_alias);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+
+ SLOT_DBG("slot index: %u, vol index: %u\n", slot_index, vol_index);
+ return g_slot_drv->get_slot_vol_alias(slot_index, vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_vol_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, vol_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vol_type);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+
+ SLOT_DBG("slot index: %u, vol index: %u\n", slot_index, vol_index);
+ return g_slot_drv->get_slot_vol_type(slot_index, vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_vol_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, vol_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vol_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+
+ SLOT_DBG("slot index: %u, vol index: %u\n", slot_index, vol_index);
+ return g_slot_drv->get_slot_vol_max(slot_index, vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_vol_max_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, vol_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_vol_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+ ret = g_slot_drv->set_slot_vol_max(slot_index, vol_index, buf, count);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u vol%u max threshold failed, value: %s, count: %lu, ret: %d\n",
+ slot_index, vol_index, buf, count, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u vol%u max threshold success, value: %s, count: %lu, ret: %d\n",
+ slot_index, vol_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t slot_vol_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, vol_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vol_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+
+ SLOT_DBG("slot index: %u, vol index: %u\n", slot_index, vol_index);
+ return g_slot_drv->get_slot_vol_min(slot_index, vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_vol_min_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, vol_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_vol_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+ ret = g_slot_drv->set_slot_vol_min(slot_index, vol_index, buf, count);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u vol%u min threshold failed, value: %s, count: %lu, ret: %d\n",
+ slot_index, vol_index, buf, count, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u vol%u min threshold success, value: %s, count: %lu, ret: %d\n",
+ slot_index, vol_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t slot_vol_range_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, vol_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vol_range);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+
+ SLOT_DBG("slot index: %u, vol index: %u\n", slot_index, vol_index);
+ return g_slot_drv->get_slot_vol_range(slot_index, vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_vol_nominal_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, vol_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_vol_nominal_value);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ vol_index = obj->index;
+
+ SLOT_DBG("slot index: %u, vol index: %u\n", slot_index, vol_index);
+ return g_slot_drv->get_slot_vol_nominal_value(slot_index, vol_index, buf, PAGE_SIZE);
+}
+/**********************************end of slot vol**********************************************/
+/*************************************slot curr*************************************************/
+static ssize_t slot_curr_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, curr_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_curr_value);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ curr_index = obj->index;
+
+ SLOT_DBG("slot index: %u, curr index: %u\n", slot_index, curr_index);
+ return g_slot_drv->get_slot_curr_value(slot_index, curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_curr_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, curr_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_curr_alias);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ curr_index = obj->index;
+
+ SLOT_DBG("slot index: %u, curr index: %u\n", slot_index, curr_index);
+ return g_slot_drv->get_slot_curr_alias(slot_index, curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_curr_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, curr_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_curr_type);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ curr_index = obj->index;
+
+ SLOT_DBG("slot index: %u, curr index: %u\n", slot_index, curr_index);
+ return g_slot_drv->get_slot_curr_type(slot_index, curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_curr_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, curr_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_curr_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ curr_index = obj->index;
+
+ SLOT_DBG("slot index: %u, curr index: %u\n", slot_index, curr_index);
+ return g_slot_drv->get_slot_curr_max(slot_index, curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_curr_max_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, curr_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_curr_max);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ curr_index = obj->index;
+ return g_slot_drv->set_slot_curr_max(slot_index, curr_index, buf, count);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u curr%u max threshold failed, value: %s, count: %lu, ret: %d\n",
+ slot_index, curr_index, buf, count, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u curr%u max threshold success, value: %s, count: %lu, ret: %d\n",
+ slot_index, curr_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t slot_curr_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, curr_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_curr_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ curr_index = obj->index;
+
+ SLOT_DBG("slot index: %u, curr index: %u\n", slot_index, curr_index);
+ return g_slot_drv->get_slot_curr_min(slot_index, curr_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_curr_min_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, curr_index;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_curr_min);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ curr_index = obj->index;
+ ret = g_slot_drv->set_slot_curr_min(slot_index, curr_index, buf, count);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u curr%u min threshold failed, value: %s, count: %lu, ret: %d\n",
+ slot_index, curr_index, buf, count, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u curr%u min threshold success, value: %s, count: %lu, ret: %d\n",
+ slot_index, curr_index, buf, count, ret);
+ return count;
+}
+/**********************************end of slot curr**********************************************/
+/*************************************slot fpga*************************************************/
+static ssize_t slot_fpga_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, fpga_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_fpga_alias);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ fpga_index = obj->index;
+
+ SLOT_DBG("slot index: %u, fpga index: %u\n", slot_index, fpga_index);
+ return g_slot_drv->get_slot_fpga_alias(slot_index, fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_fpga_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, fpga_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_fpga_type);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ fpga_index = obj->index;
+
+ SLOT_DBG("slot index: %u, fpga index: %u\n", slot_index, fpga_index);
+ return g_slot_drv->get_slot_fpga_type(slot_index, fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_fpga_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index, fpga_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_fpga_firmware_version);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ fpga_index = obj->index;
+
+ SLOT_DBG("slot index: %u, fpga index: %u\n", slot_index, fpga_index);
+ return g_slot_drv->get_slot_fpga_firmware_version(slot_index, fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_fpga_board_version_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index, fpga_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_fpga_board_version);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ fpga_index = obj->index;
+
+ SLOT_DBG("slot index: %u, fpga index: %u\n", slot_index, fpga_index);
+ return g_slot_drv->get_slot_fpga_board_version(slot_index, fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_fpga_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index, fpga_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_fpga_test_reg);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ fpga_index = obj->index;
+
+ SLOT_DBG("slot index: %u, fpga index: %u\n", slot_index, fpga_index);
+ return g_slot_drv->get_slot_fpga_test_reg(slot_index, fpga_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_fpga_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, fpga_index, value;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_fpga_test_reg);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ fpga_index = obj->index;
+ sscanf(buf, "0x%x", &value);
+ ret = g_slot_drv->set_slot_fpga_test_reg(slot_index, fpga_index, value);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u fpga%u test reg failed, value:0x%x, ret: %d.\n",
+ slot_index, fpga_index, value, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u fpga%u test reg success, value: 0x%x.\n", slot_index, fpga_index, value);
+ return count;
+}
+/**********************************end of slot fpga**********************************************/
+/*************************************slot cpld*************************************************/
+static ssize_t slot_cpld_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, cpld_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_cpld_alias);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ cpld_index = obj->index;
+
+ SLOT_DBG("slot index: %u, cpld index: %u\n", slot_index, cpld_index);
+ return g_slot_drv->get_slot_cpld_alias(slot_index, cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_cpld_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int slot_index, cpld_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_cpld_type);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ cpld_index = obj->index;
+
+ SLOT_DBG("slot index: %u, cpld index: %u\n", slot_index, cpld_index);
+ return g_slot_drv->get_slot_cpld_type(slot_index, cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_cpld_fw_version_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index, cpld_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_cpld_firmware_version);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ cpld_index = obj->index;
+
+ SLOT_DBG("slot index: %u, cpld index: %u\n", slot_index, cpld_index);
+ return g_slot_drv->get_slot_cpld_firmware_version(slot_index, cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_cpld_board_version_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index, cpld_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_cpld_board_version);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ cpld_index = obj->index;
+
+ SLOT_DBG("slot index: %u, cpld index: %u\n", slot_index, cpld_index);
+ return g_slot_drv->get_slot_cpld_board_version(slot_index, cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_cpld_test_reg_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index, cpld_index;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_cpld_test_reg);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ cpld_index = obj->index;
+
+ SLOT_DBG("slot index: %u, cpld index: %u\n", slot_index, cpld_index);
+ return g_slot_drv->get_slot_cpld_test_reg(slot_index, cpld_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_cpld_test_reg_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int slot_index, cpld_index, value;
+ int ret;
+ struct switch_obj *p_obj;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_cpld_test_reg);
+
+ p_obj = to_switch_obj(obj->kobj.parent);
+ slot_index = p_obj->index;
+ cpld_index = obj->index;
+ sscanf(buf, "0x%x", &value);
+ ret = g_slot_drv->set_slot_cpld_test_reg(slot_index, cpld_index, value);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u cpld%u test reg failed, value:0x%x, ret: %d.\n",
+ slot_index, cpld_index, value, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u cpld%u test reg success, value: 0x%x.\n", slot_index, cpld_index, value);
+ return count;
+}
+
+static ssize_t slot_power_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int slot_index;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->get_slot_power_status);
+
+ slot_index = obj->index;
+ SLOT_DBG("slot index: %u\n", slot_index);
+ return g_slot_drv->get_slot_power_status(slot_index, buf, PAGE_SIZE);
+}
+
+static ssize_t slot_power_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int slot_index;
+ int ret, power;
+
+ check_p(g_slot_drv);
+ check_p(g_slot_drv->set_slot_power_status);
+
+ slot_index = obj->index;
+ ret = kstrtoint(buf, 0, &power);
+ if (ret != 0) {
+ SLOT_ERR("invaild slot power status ret: %d, buf: %s.\n", ret, buf);
+ return -EINVAL;
+ }
+ SLOT_DBG("slot index: %u, power: %d\n", slot_index, power);
+ ret = g_slot_drv->set_slot_power_status(slot_index, power);
+ if (ret < 0) {
+ SLOT_ERR("set slot%u power: %d failed, ret: %d\n", slot_index, power, ret);
+ return ret;
+ }
+ SLOT_DBG("set slot%u power: %d success\n", slot_index, power);
+ return count;
+}
+/**********************************end of slot cpld**********************************************/
+/**********************************slot dir and attrs********************************************/
+static struct switch_attribute slot_number_attr = __ATTR(number, S_IRUGO, slot_number_show, NULL);
+
+static struct attribute *slot_dir_attrs[] = {
+ &slot_number_attr.attr,
+ NULL,
+};
+
+static struct attribute_group slot_root_attr_group = {
+ .attrs = slot_dir_attrs,
+};
+
+/*******************************slot[1-n] dir and attrs*******************************************/
+static struct switch_attribute slot_model_name_attr = __ATTR(model_name, S_IRUGO, slot_model_name_show, NULL);
+static struct switch_attribute slot_vendor_attr = __ATTR(vendor, S_IRUGO, slot_vendor_show, NULL);
+static struct switch_attribute slot_hw_attr = __ATTR(hardware_version, S_IRUGO, slot_hw_show, NULL);
+static struct switch_attribute slot_sn_attr = __ATTR(serial_number, S_IRUGO, slot_sn_show, NULL);
+static struct switch_attribute slot_pn_attr = __ATTR(part_number, S_IRUGO, slot_pn_show, NULL);
+static struct switch_attribute slot_status_attr = __ATTR(status, S_IRUGO, slot_status_show, NULL);
+static struct switch_attribute slot_led_status_attr = __ATTR(led_status, S_IRUGO | S_IWUSR, slot_led_status_show, slot_led_status_store);
+static struct switch_attribute slot_power_on_attr = __ATTR(power_on, S_IRUGO | S_IWUSR, slot_power_show, slot_power_store);
+static struct switch_attribute num_temp_sensors_attr = __ATTR(num_temp_sensors, S_IRUGO, slot_temp_number_show, NULL);
+static struct switch_attribute num_vol_sensors_attr = __ATTR(num_vol_sensors, S_IRUGO, slot_vol_number_show, NULL);
+static struct switch_attribute num_curr_sensors_attr = __ATTR(num_curr_sensors, S_IRUGO, slot_curr_number_show, NULL);
+static struct switch_attribute num_fpga_attr = __ATTR(num_fpgas, S_IRUGO, slot_fpga_number_show, NULL);
+static struct switch_attribute num_cpld_attr = __ATTR(num_cplds, S_IRUGO, slot_cpld_number_show, NULL);
+
+static struct attribute *slot_attrs[] = {
+ &slot_model_name_attr.attr,
+ &slot_vendor_attr.attr,
+ &slot_power_on_attr.attr,
+ &slot_hw_attr.attr,
+ &slot_sn_attr.attr,
+ &slot_pn_attr.attr,
+ &slot_status_attr.attr,
+ &slot_led_status_attr.attr,
+ &num_temp_sensors_attr.attr,
+ &num_vol_sensors_attr.attr,
+ &num_curr_sensors_attr.attr,
+ &num_fpga_attr.attr,
+ &num_cpld_attr.attr,
+ NULL,
+};
+
+static struct attribute_group slot_attr_group = {
+ .attrs = slot_attrs,
+};
+
+/*******************************slot temp[1-n] dir and attrs*******************************************/
+static struct switch_attribute slot_temp_alias_attr = __ATTR(alias, S_IRUGO, slot_temp_alias_show, NULL);
+static struct switch_attribute slot_temp_type_attr = __ATTR(type, S_IRUGO, slot_temp_type_show, NULL);
+static struct switch_attribute slot_temp_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, slot_temp_max_show, slot_temp_max_store);
+static struct switch_attribute slot_temp_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, slot_temp_min_show, slot_temp_min_store);
+static struct switch_attribute slot_temp_value_attr = __ATTR(value, S_IRUGO, slot_temp_value_show, NULL);
+
+static struct attribute *slot_temp_attrs[] = {
+ &slot_temp_alias_attr.attr,
+ &slot_temp_type_attr.attr,
+ &slot_temp_max_attr.attr,
+ &slot_temp_min_attr.attr,
+ &slot_temp_value_attr.attr,
+ NULL,
+};
+
+static struct attribute_group slot_temp_attr_group = {
+ .attrs = slot_temp_attrs,
+};
+
+/*******************************slot vol[1-n] dir and attrs*******************************************/
+static struct switch_attribute slot_vol_alias_attr = __ATTR(alias, S_IRUGO, slot_vol_alias_show, NULL);
+static struct switch_attribute slot_vol_type_attr = __ATTR(type, S_IRUGO, slot_vol_type_show, NULL);
+static struct switch_attribute slot_vol_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, slot_vol_max_show, slot_vol_max_store);
+static struct switch_attribute slot_vol_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, slot_vol_min_show, slot_vol_min_store);
+static struct switch_attribute slot_vol_value_attr = __ATTR(value, S_IRUGO, slot_vol_value_show, NULL);
+static struct switch_attribute slot_vol_range_attr = __ATTR(range, S_IRUGO, slot_vol_range_show, NULL);
+static struct switch_attribute slot_vol_nominal_value_attr = __ATTR(nominal_value, S_IRUGO, slot_vol_nominal_value_show, NULL);
+
+static struct attribute *slot_vol_attrs[] = {
+ &slot_vol_alias_attr.attr,
+ &slot_vol_type_attr.attr,
+ &slot_vol_max_attr.attr,
+ &slot_vol_min_attr.attr,
+ &slot_vol_value_attr.attr,
+ &slot_vol_range_attr.attr,
+ &slot_vol_nominal_value_attr.attr,
+ NULL,
+};
+
+static struct attribute_group slot_vol_attr_group = {
+ .attrs = slot_vol_attrs,
+};
+
+/*******************************slot curr[1-n] dir and attrs*******************************************/
+static struct switch_attribute slot_curr_alias_attr = __ATTR(alias, S_IRUGO, slot_curr_alias_show, NULL);
+static struct switch_attribute slot_curr_type_attr = __ATTR(type, S_IRUGO, slot_curr_type_show, NULL);
+static struct switch_attribute slot_curr_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, slot_curr_max_show, slot_curr_max_store);
+static struct switch_attribute slot_curr_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, slot_curr_min_show, slot_curr_min_store);
+static struct switch_attribute slot_curr_value_attr = __ATTR(value, S_IRUGO, slot_curr_value_show, NULL);
+
+static struct attribute *slot_curr_attrs[] = {
+ &slot_curr_alias_attr.attr,
+ &slot_curr_type_attr.attr,
+ &slot_curr_max_attr.attr,
+ &slot_curr_min_attr.attr,
+ &slot_curr_value_attr.attr,
+ NULL,
+};
+
+static struct attribute_group slot_curr_attr_group = {
+ .attrs = slot_curr_attrs,
+};
+
+/*******************************slot fpga[1-n] dir and attrs*******************************************/
+static struct switch_attribute slot_fpga_alias_attr = __ATTR(alias, S_IRUGO, slot_fpga_alias_show, NULL);
+static struct switch_attribute slot_fpga_type_attr = __ATTR(type, S_IRUGO, slot_fpga_type_show, NULL);
+static struct switch_attribute slot_fpga_fw_version_attr = __ATTR(firmware_version, S_IRUGO, slot_fpga_fw_version_show, NULL);
+static struct switch_attribute slot_fpga_board_version_attr = __ATTR(board_version, S_IRUGO, slot_fpga_board_version_show, NULL);
+static struct switch_attribute slot_fpga_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, slot_fpga_test_reg_show, slot_fpga_test_reg_store);
+
+static struct attribute *slot_fpga_attrs[] = {
+ &slot_fpga_alias_attr.attr,
+ &slot_fpga_type_attr.attr,
+ &slot_fpga_fw_version_attr.attr,
+ &slot_fpga_board_version_attr.attr,
+ &slot_fpga_test_reg_attr.attr,
+ NULL,
+};
+
+static struct attribute_group slot_fpga_attr_group = {
+ .attrs = slot_fpga_attrs,
+};
+
+/*******************************slot cpld[1-n] dir and attrs*******************************************/
+static struct switch_attribute slot_cpld_alias_attr = __ATTR(alias, S_IRUGO, slot_cpld_alias_show, NULL);
+static struct switch_attribute slot_cpld_type_attr = __ATTR(type, S_IRUGO, slot_cpld_type_show, NULL);
+static struct switch_attribute slot_cpld_fw_version_attr = __ATTR(firmware_version, S_IRUGO, slot_cpld_fw_version_show, NULL);
+static struct switch_attribute slot_cpld_board_version_attr = __ATTR(board_version, S_IRUGO, slot_cpld_board_version_show, NULL);
+static struct switch_attribute slot_cpld_test_reg_attr = __ATTR(reg_test, S_IRUGO | S_IWUSR, slot_cpld_test_reg_show, slot_cpld_test_reg_store);
+
+static struct attribute *slot_cpld_attrs[] = {
+ &slot_cpld_alias_attr.attr,
+ &slot_cpld_type_attr.attr,
+ &slot_cpld_fw_version_attr.attr,
+ &slot_cpld_board_version_attr.attr,
+ &slot_cpld_test_reg_attr.attr,
+ NULL,
+};
+
+static struct attribute_group slot_cpld_attr_group = {
+ .attrs = slot_cpld_attrs,
+};
+
+/***************************************slot cpld*****************************************/
+static void slotindex_single_cpld_remove_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int cpld_index)
+{
+ struct slot_cpld_obj_s *curr_cpld;
+
+ curr_cpld = &curr_slot->cpld[cpld_index - 1];
+ if (curr_cpld->obj) {
+ sysfs_remove_group(&curr_cpld->obj->kobj, &slot_cpld_attr_group);
+ switch_kobject_delete(&curr_cpld->obj);
+ SLOT_DBG("delete slot%u cpld%u dir and attrs success.\n", curr_slot->obj->index,
+ cpld_index);
+ }
+ return;
+}
+
+static int slotindex_single_cpld_create_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int cpld_index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct slot_cpld_obj_s *curr_cpld;
+
+ curr_cpld = &curr_slot->cpld[cpld_index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "cpld%u", cpld_index);
+ curr_cpld->obj = switch_kobject_create(name, &curr_slot->obj->kobj);
+ if (!curr_cpld->obj) {
+ SLOT_ERR("create slot%u %s object error!\n", curr_slot->obj->index, name);
+ return -ENOMEM;
+ }
+ curr_cpld->obj->index = cpld_index;
+ if (sysfs_create_group(&curr_cpld->obj->kobj, &slot_cpld_attr_group) != 0) {
+ SLOT_ERR("create slot%u %s attrs error.\n", curr_slot->obj->index, name);
+ switch_kobject_delete(&curr_cpld->obj);
+ return -EBADRQC;
+ }
+ SLOT_DBG("create slot%u %s success.\n", curr_slot->obj->index, name);
+ return 0;
+}
+
+static void slotindex_cpld_remove_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int cpld_index, cpld_num;
+
+ if (curr_slot->cpld) {
+ cpld_num = curr_slot->cpld_number;
+ for (cpld_index = cpld_num; cpld_index > 0; cpld_index--) {
+ slotindex_single_cpld_remove_kobj_and_attrs(curr_slot, cpld_index);
+ }
+ kfree(curr_slot->cpld);
+ curr_slot->cpld = NULL;
+ }
+ return;
+}
+
+static int slotindex_cpld_create_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int cpld_index, i, cpld_num;
+
+ cpld_num = curr_slot->cpld_number;
+ curr_slot->cpld = kzalloc(sizeof(struct slot_cpld_obj_s) * cpld_num, GFP_KERNEL);
+ if (!curr_slot->cpld) {
+ SLOT_ERR("kzalloc slot cpld error, slot index: %u, cpld number: %u.\n",
+ curr_slot->obj->index, cpld_num);
+ return -ENOMEM;
+ }
+
+ for (cpld_index = 1; cpld_index <= cpld_num; cpld_index++) {
+ if (slotindex_single_cpld_create_kobj_and_attrs(curr_slot, cpld_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = cpld_index; i > 0; i--) {
+ slotindex_single_cpld_remove_kobj_and_attrs(curr_slot, i);
+ }
+ kfree(curr_slot->cpld);
+ curr_slot->cpld = NULL;
+ return -EBADRQC;
+}
+
+/* create slot cpld[1-n] directory and attributes*/
+static int slot_cpld_create(void)
+{
+ int cpld_num;
+ unsigned int slot_index, i;
+ struct slot_obj_s *curr_slot;
+
+ check_p(g_slot_drv->get_slot_cpld_number);
+ for (slot_index = 1; slot_index <= g_slot.slot_number; slot_index++) {
+ cpld_num = g_slot_drv->get_slot_cpld_number(slot_index);
+ if (cpld_num <= 0) {
+ SLOT_DBG("slot%u cpld number: %d, don't need to create cpld* dirs and attrs.\n",
+ slot_index, cpld_num);
+ continue;
+ }
+ curr_slot = &g_slot.slot[slot_index - 1];
+ curr_slot->cpld_number = cpld_num;
+ if (slotindex_cpld_create_kobj_and_attrs(curr_slot) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = slot_index; i > 0; i--) {
+ curr_slot = &g_slot.slot[i - 1];
+ slotindex_cpld_remove_kobj_and_attrs(curr_slot);
+ }
+ return -EBADRQC;
+}
+
+/* delete slot cpld[1-n] directory and attributes*/
+static void slot_cpld_remove(void)
+{
+ unsigned int slot_index;
+ struct slot_obj_s *curr_slot;
+
+ if (g_slot.slot) {
+ for (slot_index = g_slot.slot_number; slot_index > 0; slot_index--) {
+ curr_slot = &g_slot.slot[slot_index - 1];
+ slotindex_cpld_remove_kobj_and_attrs(curr_slot);
+ curr_slot->cpld_number = 0;
+ }
+ }
+ return;
+}
+/************************************end of slot cpld**************************************/
+/***************************************slot fpga*****************************************/
+static void slotindex_single_fpga_remove_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int fpga_index)
+{
+ struct slot_fpga_obj_s *curr_fpga;
+
+ curr_fpga = &curr_slot->fpga[fpga_index - 1];
+ if (curr_fpga->obj) {
+ sysfs_remove_group(&curr_fpga->obj->kobj, &slot_fpga_attr_group);
+ switch_kobject_delete(&curr_fpga->obj);
+ SLOT_DBG("delete slot%u fpga%u dir and attrs success.\n", curr_slot->obj->index,
+ fpga_index);
+ }
+ return;
+}
+
+static int slotindex_single_fpga_create_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int fpga_index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct slot_fpga_obj_s *curr_fpga;
+
+ curr_fpga = &curr_slot->fpga[fpga_index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "fpga%u", fpga_index);
+ curr_fpga->obj = switch_kobject_create(name, &curr_slot->obj->kobj);
+ if (!curr_fpga->obj) {
+ SLOT_ERR("create slot%u %s object error!\n", curr_slot->obj->index, name);
+ return -ENOMEM;
+ }
+ curr_fpga->obj->index = fpga_index;
+ if (sysfs_create_group(&curr_fpga->obj->kobj, &slot_fpga_attr_group) != 0) {
+ SLOT_ERR("create slot%u %s attrs error.\n", curr_slot->obj->index, name);
+ switch_kobject_delete(&curr_fpga->obj);
+ return -EBADRQC;
+ }
+ SLOT_DBG("create slot%u %s success.\n", curr_slot->obj->index, name);
+ return 0;
+}
+
+static void slotindex_fpga_remove_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int fpga_index, fpga_num;
+
+ if (curr_slot->fpga) {
+ fpga_num = curr_slot->fpga_number;
+ for (fpga_index = fpga_num; fpga_index > 0; fpga_index--) {
+ slotindex_single_fpga_remove_kobj_and_attrs(curr_slot, fpga_index);
+ }
+ kfree(curr_slot->fpga);
+ curr_slot->fpga = NULL;
+ }
+ return;
+}
+
+static int slotindex_fpga_create_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int fpga_index, i, fpga_num;
+
+ fpga_num = curr_slot->fpga_number;
+ curr_slot->fpga = kzalloc(sizeof(struct slot_fpga_obj_s) * fpga_num, GFP_KERNEL);
+ if (!curr_slot->fpga) {
+ SLOT_ERR("kzalloc slot fpga error, slot index: %u, fpga number: %u.\n",
+ curr_slot->obj->index, fpga_num);
+ return -ENOMEM;
+ }
+
+ for (fpga_index = 1; fpga_index <= fpga_num; fpga_index++) {
+ if (slotindex_single_fpga_create_kobj_and_attrs(curr_slot, fpga_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = fpga_index; i > 0; i--) {
+ slotindex_single_fpga_remove_kobj_and_attrs(curr_slot, i);
+ }
+ kfree(curr_slot->fpga);
+ curr_slot->fpga = NULL;
+ return -EBADRQC;
+}
+
+/* create slot fpga[1-n] directory and attributes*/
+static int slot_fpga_create(void)
+{
+ int fpga_num;
+ unsigned int slot_index, i;
+ struct slot_obj_s *curr_slot;
+
+ check_p(g_slot_drv->get_slot_fpga_number);
+ for (slot_index = 1; slot_index <= g_slot.slot_number; slot_index++) {
+ fpga_num = g_slot_drv->get_slot_fpga_number(slot_index);
+ if (fpga_num <= 0) {
+ SLOT_DBG("slot%u fpga number: %d, don't need to create fpga* dirs and attrs.\n",
+ slot_index, fpga_num);
+ continue;
+ }
+ curr_slot = &g_slot.slot[slot_index - 1];
+ curr_slot->fpga_number = fpga_num;
+ if (slotindex_fpga_create_kobj_and_attrs(curr_slot) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = slot_index; i > 0; i--) {
+ curr_slot = &g_slot.slot[i - 1];
+ slotindex_fpga_remove_kobj_and_attrs(curr_slot);
+ }
+ return -EBADRQC;
+}
+
+/* delete slot fpga[1-n] directory and attributes*/
+static void slot_fpga_remove(void)
+{
+ unsigned int slot_index;
+ struct slot_obj_s *curr_slot;
+
+ if (g_slot.slot) {
+ for (slot_index = g_slot.slot_number; slot_index > 0; slot_index--) {
+ curr_slot = &g_slot.slot[slot_index - 1];
+ slotindex_fpga_remove_kobj_and_attrs(curr_slot);
+ curr_slot->fpga_number = 0;
+ }
+ }
+ return;
+}
+/************************************end of slot fpga**************************************/
+/*************************************slot current*****************************************/
+static void slotindex_single_curr_remove_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int curr_index)
+{
+ struct slot_curr_obj_s *curr;
+
+ curr = &curr_slot->curr[curr_index - 1];
+ if (curr->obj) {
+ sysfs_remove_group(&curr->obj->kobj, &slot_curr_attr_group);
+ switch_kobject_delete(&curr->obj);
+ SLOT_DBG("delete slot%u curr_sensor%u dir and attrs success.\n", curr_slot->obj->index,
+ curr_index);
+ }
+ return;
+}
+
+static int slotindex_single_curr_create_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int curr_index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct slot_curr_obj_s *curr;
+
+ curr = &curr_slot->curr[curr_index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "curr_sensor%u", curr_index);
+ curr->obj = switch_kobject_create(name, &curr_slot->obj->kobj);
+ if (!curr->obj) {
+ SLOT_ERR("create slot%u %s object error!\n", curr_slot->obj->index, name);
+ return -ENOMEM;
+ }
+ curr->obj->index = curr_index;
+ if (sysfs_create_group(&curr->obj->kobj, &slot_curr_attr_group) != 0) {
+ SLOT_ERR("create slot%u %s attrs error.\n", curr_slot->obj->index, name);
+ switch_kobject_delete(&curr->obj);
+ return -EBADRQC;
+ }
+ SLOT_DBG("create slot%u %s success.\n", curr_slot->obj->index, name);
+ return 0;
+}
+
+static void slotindex_curr_remove_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int curr_index, curr_num;
+
+ if (curr_slot->curr) {
+ curr_num = curr_slot->curr_number;
+ for (curr_index = curr_num; curr_index > 0; curr_index--) {
+ slotindex_single_curr_remove_kobj_and_attrs(curr_slot, curr_index);
+ }
+ kfree(curr_slot->curr);
+ curr_slot->curr = NULL;
+ }
+ return;
+}
+
+static int slotindex_curr_create_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int curr_index, i, curr_num;
+
+ curr_num = curr_slot->curr_number;
+ curr_slot->curr = kzalloc(sizeof(struct slot_curr_obj_s) * curr_num, GFP_KERNEL);
+ if (!curr_slot->curr) {
+ SLOT_ERR("kzalloc slot curr error, slot index: %u, curr number: %u.\n",
+ curr_slot->obj->index, curr_num);
+ return -ENOMEM;
+ }
+
+ for (curr_index = 1; curr_index <= curr_num; curr_index++) {
+ if (slotindex_single_curr_create_kobj_and_attrs(curr_slot, curr_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = curr_index; i > 0; i--) {
+ slotindex_single_curr_remove_kobj_and_attrs(curr_slot, i);
+ }
+ kfree(curr_slot->curr);
+ curr_slot->curr = NULL;
+ return -EBADRQC;
+}
+
+/* create slot curr_snesor[1-n] directory and attributes*/
+static int slot_curr_create(void)
+{
+ int curr_num;
+ unsigned int slot_index, i;
+ struct slot_obj_s *curr_slot;
+
+ check_p(g_slot_drv->get_slot_curr_number);
+ for (slot_index = 1; slot_index <= g_slot.slot_number; slot_index++) {
+ curr_num = g_slot_drv->get_slot_curr_number(slot_index);
+ if (curr_num <= 0) {
+ SLOT_DBG("slot%u curr number: %d, don't need to create curr_sensor* dirs and attrs.\n",
+ slot_index, curr_num);
+ continue;
+ }
+ curr_slot = &g_slot.slot[slot_index - 1];
+ curr_slot->curr_number = curr_num;
+ if (slotindex_curr_create_kobj_and_attrs(curr_slot) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = slot_index; i > 0; i--) {
+ curr_slot = &g_slot.slot[i - 1];
+ slotindex_curr_remove_kobj_and_attrs(curr_slot);
+ }
+ return -EBADRQC;
+}
+
+/* delete slot curr_sensor[1-n] directory and attributes*/
+static void slot_curr_remove(void)
+{
+ unsigned int slot_index;
+ struct slot_obj_s *curr_slot;
+
+ if (g_slot.slot) {
+ for (slot_index = g_slot.slot_number; slot_index > 0; slot_index--) {
+ curr_slot = &g_slot.slot[slot_index - 1];
+ slotindex_curr_remove_kobj_and_attrs(curr_slot);
+ curr_slot->curr_number = 0;
+ }
+ }
+ return;
+}
+/**********************************end of slot current************************************/
+/*************************************slot voltage****************************************/
+static void slotindex_single_vol_remove_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int vol_index)
+{
+ struct slot_vol_obj_s *curr_vol;
+
+ curr_vol = &curr_slot->vol[vol_index - 1];
+ if (curr_vol->obj) {
+ sysfs_remove_group(&curr_vol->obj->kobj, &slot_vol_attr_group);
+ switch_kobject_delete(&curr_vol->obj);
+ SLOT_DBG("delete slot%u vol_sensor%u dir and attrs success.\n", curr_slot->obj->index,
+ vol_index);
+ }
+ return;
+}
+
+static int slotindex_single_vol_create_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int vol_index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct slot_vol_obj_s *curr_vol;
+
+ curr_vol = &curr_slot->vol[vol_index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "vol_sensor%u", vol_index);
+ curr_vol->obj = switch_kobject_create(name, &curr_slot->obj->kobj);
+ if (!curr_vol->obj) {
+ SLOT_ERR("create slot%u %s object error!\n", curr_slot->obj->index, name);
+ return -ENOMEM;
+ }
+ curr_vol->obj->index = vol_index;
+ if (sysfs_create_group(&curr_vol->obj->kobj, &slot_vol_attr_group) != 0) {
+ SLOT_ERR("create slot%u %s attrs error.\n", curr_slot->obj->index, name);
+ switch_kobject_delete(&curr_vol->obj);
+ return -EBADRQC;
+ }
+ SLOT_DBG("create slot%u %s success.\n", curr_slot->obj->index, name);
+ return 0;
+}
+
+static void slotindex_vol_remove_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int vol_index, vol_num;
+
+ if (curr_slot->vol) {
+ vol_num = curr_slot->vol_number;
+ for (vol_index = vol_num; vol_index > 0; vol_index--) {
+ slotindex_single_vol_remove_kobj_and_attrs(curr_slot, vol_index);
+ }
+ kfree(curr_slot->vol);
+ curr_slot->vol = NULL;
+ }
+ return;
+}
+
+static int slotindex_vol_create_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int vol_index, i, vol_num;
+
+ vol_num = curr_slot->vol_number;
+ curr_slot->vol = kzalloc(sizeof(struct slot_vol_obj_s) * vol_num, GFP_KERNEL);
+ if (!curr_slot->vol) {
+ SLOT_ERR("kzalloc slot vol error, slot index: %u, vol number: %u.\n",
+ curr_slot->obj->index, vol_num);
+ return -ENOMEM;
+ }
+
+ for (vol_index = 1; vol_index <= vol_num; vol_index++) {
+ if (slotindex_single_vol_create_kobj_and_attrs(curr_slot, vol_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = vol_index; i > 0; i--) {
+ slotindex_single_vol_remove_kobj_and_attrs(curr_slot, i);
+ }
+ kfree(curr_slot->vol);
+ curr_slot->vol = NULL;
+ return -EBADRQC;
+}
+
+/* create slot vol_snesor[1-n] directory and attributes*/
+static int slot_vol_create(void)
+{
+ int vol_num;
+ unsigned int slot_index, i;
+ struct slot_obj_s *curr_slot;
+
+ check_p(g_slot_drv->get_slot_vol_number);
+ for (slot_index = 1; slot_index <= g_slot.slot_number; slot_index++) {
+ vol_num = g_slot_drv->get_slot_vol_number(slot_index);
+ if (vol_num <= 0) {
+ SLOT_DBG("slot%u vol number: %d, don't need to create vol_sensor* dirs and attrs.\n",
+ slot_index, vol_num);
+ continue;
+ }
+ curr_slot = &g_slot.slot[slot_index - 1];
+ curr_slot->vol_number = vol_num;
+ if (slotindex_vol_create_kobj_and_attrs(curr_slot) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = slot_index; i > 0; i--) {
+ curr_slot = &g_slot.slot[i - 1];
+ slotindex_vol_remove_kobj_and_attrs(curr_slot);
+ }
+ return -EBADRQC;
+}
+
+/* delete slot vol_sensor[1-n] directory and attributes*/
+static void slot_vol_remove(void)
+{
+ unsigned int slot_index;
+ struct slot_obj_s *curr_slot;
+
+ if (g_slot.slot) {
+ for (slot_index = g_slot.slot_number; slot_index > 0; slot_index--) {
+ curr_slot = &g_slot.slot[slot_index - 1];
+ slotindex_vol_remove_kobj_and_attrs(curr_slot);
+ curr_slot->vol_number = 0;
+ }
+ }
+ return;
+}
+/**********************************end of slot voltage************************************/
+/***************************************slot temp*****************************************/
+static void slotindex_single_temp_remove_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int temp_index)
+{
+ struct slot_temp_obj_s *curr_temp;
+
+ curr_temp = &curr_slot->temp[temp_index - 1];
+ if (curr_temp->obj) {
+ sysfs_remove_group(&curr_temp->obj->kobj, &slot_temp_attr_group);
+ switch_kobject_delete(&curr_temp->obj);
+ SLOT_DBG("delete slot%u temp_sensor%u dir and attrs success.\n", curr_slot->obj->index,
+ temp_index);
+ }
+ return;
+}
+
+static int slotindex_single_temp_create_kobj_and_attrs(struct slot_obj_s *curr_slot,
+ unsigned int temp_index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct slot_temp_obj_s *curr_temp;
+
+ curr_temp = &curr_slot->temp[temp_index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "temp_sensor%u", temp_index);
+ curr_temp->obj = switch_kobject_create(name, &curr_slot->obj->kobj);
+ if (!curr_temp->obj) {
+ SLOT_ERR("create slot%u %s object error!\n", curr_slot->obj->index, name);
+ return -ENOMEM;
+ }
+ curr_temp->obj->index = temp_index;
+ if (sysfs_create_group(&curr_temp->obj->kobj, &slot_temp_attr_group) != 0) {
+ SLOT_ERR("create slot%u %s attrs error.\n", curr_slot->obj->index, name);
+ switch_kobject_delete(&curr_temp->obj);
+ return -EBADRQC;
+ }
+ SLOT_DBG("create slot%u %s success.\n", curr_slot->obj->index, name);
+ return 0;
+}
+
+static void slotindex_temp_remove_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int temp_index, temp_num;
+
+ if (curr_slot->temp) {
+ temp_num = curr_slot->temp_number;
+ for (temp_index = temp_num; temp_index > 0; temp_index--) {
+ slotindex_single_temp_remove_kobj_and_attrs(curr_slot, temp_index);
+ }
+ kfree(curr_slot->temp);
+ curr_slot->temp = NULL;
+ }
+ return;
+}
+
+static int slotindex_temp_create_kobj_and_attrs(struct slot_obj_s *curr_slot)
+{
+ unsigned int temp_index, i, temp_num;
+
+ temp_num = curr_slot->temp_number;
+ curr_slot->temp = kzalloc(sizeof(struct slot_temp_obj_s) * temp_num, GFP_KERNEL);
+ if (!curr_slot->temp) {
+ SLOT_ERR("kzalloc slot temp error, slot index: %u, temp number: %u.\n",
+ curr_slot->obj->index, temp_num);
+ return -ENOMEM;
+ }
+
+ for (temp_index = 1; temp_index <= temp_num; temp_index++) {
+ if (slotindex_single_temp_create_kobj_and_attrs(curr_slot, temp_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = temp_index; i > 0; i--) {
+ slotindex_single_temp_remove_kobj_and_attrs(curr_slot, i);
+ }
+ kfree(curr_slot->temp);
+ curr_slot->temp = NULL;
+ return -EBADRQC;
+}
+
+/* create slot temp_sensor[1-n] directory and attributes*/
+static int slot_temp_create(void)
+{
+ int temp_num;
+ unsigned int slot_index, i;
+ struct slot_obj_s *curr_slot;
+
+ check_p(g_slot_drv->get_slot_temp_number);
+ for (slot_index = 1; slot_index <= g_slot.slot_number; slot_index++) {
+ temp_num = g_slot_drv->get_slot_temp_number(slot_index);
+ if (temp_num <= 0) {
+ SLOT_DBG("slot%u temp number: %d, don't need to create temp_sensor* dirs and attrs.\n",
+ slot_index, temp_num);
+ continue;
+ }
+ curr_slot = &g_slot.slot[slot_index - 1];
+ curr_slot->temp_number = temp_num;
+ if (slotindex_temp_create_kobj_and_attrs(curr_slot) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = slot_index; i > 0; i--) {
+ curr_slot = &g_slot.slot[i - 1];
+ slotindex_temp_remove_kobj_and_attrs(curr_slot);
+ }
+ return -EBADRQC;
+}
+
+/* delete slot temp_sensor[1-n] directory and attributes*/
+static void slot_temp_remove(void)
+{
+ unsigned int slot_index;
+ struct slot_obj_s *curr_slot;
+
+ if (g_slot.slot) {
+ for (slot_index = g_slot.slot_number; slot_index > 0; slot_index--) {
+ curr_slot = &g_slot.slot[slot_index - 1];
+ slotindex_temp_remove_kobj_and_attrs(curr_slot);
+ curr_slot->temp_number = 0;
+ }
+ }
+ return;
+}
+/************************************end of slot temp**************************************/
+
+static int slot_child_obj_create(void)
+{
+ int ret;
+
+ if (g_slot.slot_number <= 0) {
+ SLOT_DBG("slot number: %u, skip to create slot child dirs and attrs.\n",
+ g_slot.slot_number);
+ return 0;
+ }
+ /* temp create */
+ ret = slot_temp_create();
+ if (ret < 0) {
+ goto temp_err;
+ }
+ /* Voltage create */
+ ret = slot_vol_create();
+ if(ret < 0) {
+ goto vol_err;
+ }
+ /* current create */
+ ret = slot_curr_create();
+ if(ret < 0) {
+ goto curr_err;
+ }
+ /* fpga create */
+ ret = slot_fpga_create();
+ if(ret < 0) {
+ goto fpga_err;
+ }
+ /* cplf create */
+ ret = slot_cpld_create();
+ if(ret < 0) {
+ goto cpld_err;
+ }
+ return 0;
+cpld_err:
+ slot_fpga_remove();
+fpga_err:
+ slot_curr_remove();
+curr_err:
+ slot_vol_remove();
+vol_err:
+ slot_temp_remove();
+temp_err:
+ return ret;
+}
+
+static void slot_child_obj_remove(void)
+{
+ slot_cpld_remove();
+ slot_fpga_remove();
+ slot_curr_remove();
+ slot_vol_remove();
+ slot_temp_remove();
+ return;
+}
+
+static void slot_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct slot_obj_s *curr_slot;
+
+ curr_slot = &g_slot.slot[index - 1];
+ if (curr_slot->obj) {
+ sysfs_remove_group(&curr_slot->obj->kobj, &slot_attr_group);
+ switch_kobject_delete(&curr_slot->obj);
+ SLOT_DBG("delete slot%u dir and attrs success.\n", index);
+ }
+
+ return;
+}
+
+static int slot_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct slot_obj_s * curr_slot;
+
+ curr_slot = &g_slot.slot[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "slot%u", index);
+ curr_slot->obj = switch_kobject_create(name, parent);
+ if (!curr_slot->obj) {
+ SLOT_ERR("create %s object error!\n", name);
+ return -EBADRQC;
+ }
+ curr_slot->obj->index = index;
+ if (sysfs_create_group(&curr_slot->obj->kobj, &slot_attr_group) != 0) {
+ SLOT_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&curr_slot->obj);
+ return -EBADRQC;
+ }
+ SLOT_DBG("create %s dir and attrs success.\n", name);
+ return 0;
+}
+
+static int slot_sub_create_kobj_and_attrs(struct kobject *parent, int slot_num)
+{
+ unsigned int slot_index, i;
+
+ g_slot.slot = kzalloc(sizeof(struct slot_obj_s) * slot_num, GFP_KERNEL);
+ if (!g_slot.slot) {
+ SLOT_ERR("kzalloc slot.slot error, slot number = %d.\n", slot_num);
+ return -ENOMEM;
+ }
+
+ for(slot_index = 1; slot_index <= slot_num; slot_index++) {
+ if(slot_sub_single_create_kobj_and_attrs(parent, slot_index) != 0 ) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for(i = slot_index; i > 0; i--) {
+ slot_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_slot.slot);
+ g_slot.slot = NULL;
+ return -EBADRQC;
+}
+
+/* create slot[1-n] directory and attributes*/
+static int slot_sub_create(void)
+{
+ int ret;
+
+ ret = slot_sub_create_kobj_and_attrs(&g_slot_obj->kobj, g_slot.slot_number);
+ return ret;
+}
+
+/* delete slot[1-n] directory and attributes*/
+static void slot_sub_remove(void)
+{
+ unsigned int slot_index;
+
+ if (g_slot.slot) {
+ for (slot_index = g_slot.slot_number; slot_index > 0; slot_index--) {
+ slot_sub_single_remove_kobj_and_attrs(slot_index);
+ }
+ kfree(g_slot.slot);
+ g_slot.slot = NULL;
+ }
+ g_slot.slot_number = 0;
+ return;
+}
+
+/* create slot directory and number attributes*/
+static int slot_root_create(void)
+{
+ g_slot_obj = switch_kobject_create("slot", NULL);
+ if (!g_slot_obj) {
+ SLOT_ERR("switch_kobject_create slot error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_slot_obj->kobj, &slot_root_attr_group) != 0) {
+ switch_kobject_delete(&g_slot_obj);
+ SLOT_ERR("create slot dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete slot directory and number attributes*/
+static void slot_root_remove(void)
+{
+ if (g_slot_obj) {
+ sysfs_remove_group(&g_slot_obj->kobj, &slot_root_attr_group);
+ switch_kobject_delete(&g_slot_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_slot_drivers_register(struct s3ip_sysfs_slot_drivers_s *drv)
+{
+ int ret, slot_num;
+
+ SLOT_INFO("s3ip_sysfs_slot_drivers_register...\n");
+ if (g_slot_drv) {
+ SLOT_ERR("g_slot_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_slot_number);
+ g_slot_drv = drv;
+
+ slot_num = g_slot_drv->get_slot_number();
+ if (slot_num <= 0) {
+ SLOT_ERR("slot number: %d, don't need to create slot dirs and attrs.\n", slot_num);
+ g_slot_drv = NULL;
+ return -EINVAL;
+ }
+
+ mem_clear(&g_slot, sizeof(struct slot_s));
+ g_slot.slot_number = slot_num;
+ ret = slot_root_create();
+ if (ret < 0) {
+ SLOT_ERR("create slot root dir and attrs failed, ret: %d\n", ret);
+ g_slot_drv = NULL;
+ return ret;
+ }
+
+ ret = slot_sub_create();
+ if (ret < 0) {
+ SLOT_ERR("create slot sub dir and attrs failed, ret: %d\n", ret);
+ slot_root_remove();
+ g_slot_drv = NULL;
+ return ret;
+ }
+
+ ret = slot_child_obj_create();
+ if (ret < 0) {
+ SLOT_ERR("create slot child dir and attrs failed, ret: %d\n", ret);
+ slot_sub_remove();
+ slot_root_remove();
+ g_slot_drv = NULL;
+ return ret;
+ }
+ SLOT_INFO("s3ip_sysfs_slot_drivers_register success.\n");
+ return 0;
+}
+
+void s3ip_sysfs_slot_drivers_unregister(void)
+{
+ if (g_slot_drv) {
+ slot_child_obj_remove();
+ slot_sub_remove();
+ slot_root_remove();
+ g_slot_drv = NULL;
+ SLOT_DBG("s3ip_sysfs_slot_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_slot_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_slot_drivers_unregister);
+module_param(g_slot_loglevel, int, 0644);
+MODULE_PARM_DESC(g_slot_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/switch.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/switch.c
new file mode 100644
index 000000000000..c34d48e4caf5
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/switch.c
@@ -0,0 +1,309 @@
+/*
+ * An switch driver for switch devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "switch.h"
+#include "syseeprom_sysfs.h"
+
+int g_switch_loglevel = 0;
+
+#define SWITCH_INFO(fmt, args...) do { \
+ if (g_switch_loglevel & INFO) { \
+ printk(KERN_INFO "[SWITCH][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SWITCH_ERR(fmt, args...) do { \
+ if (g_switch_loglevel & ERR) { \
+ printk(KERN_ERR "[SWITCH][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SWITCH_DBG(fmt, args...) do { \
+ if (g_switch_loglevel & DBG) { \
+ printk(KERN_DEBUG "[SWITCH][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct syseeprom_s {
+ struct bin_attribute bin;
+ int creat_eeprom_bin_flag;
+};
+
+static struct s3ip_sysfs_syseeprom_drivers_s *g_syseeprom_drv = NULL;
+static struct kset *switch_kset;
+static struct syseeprom_s g_syseeprom;
+
+static ssize_t switch_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+ struct switch_attribute *attribute;
+ struct switch_obj *device;
+
+ attribute = to_switch_attr(attr);
+ device = to_switch_obj(kobj);
+
+ if (!attribute->show) {
+ return -ENOSYS;
+ }
+
+ return attribute->show(device, attribute, buf);
+}
+
+static ssize_t switch_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf,
+ size_t len)
+{
+ struct switch_attribute *attribute;
+ struct switch_obj *obj;
+
+ attribute = to_switch_attr(attr);
+ obj = to_switch_obj(kobj);
+
+ if (!attribute->store) {
+ return -ENOSYS;
+ }
+
+ return attribute->store(obj, attribute, buf, len);
+}
+
+static const struct sysfs_ops switch_sysfs_ops = {
+ .show = switch_attr_show,
+ .store = switch_attr_store,
+};
+
+static void switch_obj_release(struct kobject *kobj)
+{
+ struct switch_obj *obj;
+
+ obj = to_switch_obj(kobj);
+ kfree(obj);
+ return;
+}
+
+static struct kobj_type switch_ktype = {
+ .sysfs_ops = &switch_sysfs_ops,
+ .release = switch_obj_release,
+};
+
+static ssize_t syseeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t count)
+{
+ ssize_t rd_len;
+
+ check_p(g_syseeprom_drv);
+ check_p(g_syseeprom_drv->read_syseeprom_data);
+
+ mem_clear(buf, count);
+ rd_len = g_syseeprom_drv->read_syseeprom_data(buf, offset, count);
+ if (rd_len < 0) {
+ SWITCH_ERR("read syseeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
+ offset, count, rd_len);
+ return rd_len;
+ }
+ SWITCH_DBG("read syseeprom data success, offset:0x%llx, read len:%lu, really read len:%ld.\n",
+ offset, count, rd_len);
+ return rd_len;
+}
+
+static ssize_t syseeprom_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t count)
+{
+ ssize_t wr_len;
+
+ check_p(g_syseeprom_drv);
+ check_p(g_syseeprom_drv->write_syseeprom_data);
+
+ wr_len = g_syseeprom_drv->write_syseeprom_data(buf, offset, count);
+ if (wr_len < 0) {
+ SWITCH_ERR("write syseeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
+ offset, count, wr_len);
+ return wr_len;
+ }
+ SWITCH_DBG("write syseeprom data success, offset:0x%llx, write len:%lu, really write len:%ld.\n",
+ offset, count, wr_len);
+ return wr_len;
+}
+
+static int syseeprom_create_eeprom_attrs(void)
+{
+ int ret, eeprom_size;
+
+ eeprom_size = g_syseeprom_drv->get_syseeprom_size();
+ if (eeprom_size <= 0) {
+ SWITCH_ERR("syseeprom size: %d, invalid.\n", eeprom_size);
+ return -EINVAL;
+ }
+
+ sysfs_bin_attr_init(&g_syseeprom.bin);
+ g_syseeprom.bin.attr.name = "syseeprom";
+ g_syseeprom.bin.attr.mode = 0644;
+ g_syseeprom.bin.read = syseeprom_read;
+ g_syseeprom.bin.write = syseeprom_write;
+ g_syseeprom.bin.size = eeprom_size;
+
+ ret = sysfs_create_bin_file(&switch_kset->kobj, &g_syseeprom.bin);
+ if (ret) {
+ SWITCH_ERR("create syseeprom bin error, ret: %d. \n", ret);
+ return -EBADRQC;
+ }
+ SWITCH_DBG("create syseeprom bin file success, eeprom size:%d.\n", eeprom_size);
+ g_syseeprom.creat_eeprom_bin_flag = 1;
+ return 0;
+}
+
+static void syseeprom_remove_eeprom_attrs(void)
+{
+ if (g_syseeprom.creat_eeprom_bin_flag) {
+ sysfs_remove_bin_file(&switch_kset->kobj, &g_syseeprom.bin);
+ g_syseeprom.creat_eeprom_bin_flag = 0;
+ }
+
+ return;
+}
+
+int dev_debug_file_read(char *file_name, unsigned int dev_index, char *buf, int size)
+{
+ char file_path[DIR_NAME_MAX_LEN];
+ loff_t pos;
+ struct file *filp;
+ int ret;
+
+ mem_clear(file_path, sizeof(file_path));
+ mem_clear(buf, size);
+
+ sprintf(file_path, file_name, dev_index);
+ filp = filp_open(file_path, O_RDONLY, 0);
+ if (IS_ERR(filp)) {
+ SWITCH_ERR("dev_debug_file open failed, path=%s, ret=%d\n", file_path, ret);
+ filp = NULL;
+ ret = -ENOENT;
+ return ret;
+ }
+
+ pos = 0;
+ ret = kernel_read(filp, buf, size - 1, &pos);
+ if (ret < 0) {
+ SWITCH_ERR("dev_debug_file kernel_read failed, path=%s, addr=0, size=%d, ret=%d\n", file_name, size - 1, ret);
+ filp_close(filp, NULL);
+ return ret;
+ }
+
+ filp_close(filp, NULL);
+ filp = NULL;
+ return 0;
+}
+
+int s3ip_sysfs_syseeprom_drivers_register(struct s3ip_sysfs_syseeprom_drivers_s *drv)
+{
+ int ret;
+
+ SWITCH_INFO("s3ip_sysfs_syseeprom_drivers_register...\n");
+ if (g_syseeprom_drv) {
+ SWITCH_ERR("g_syseeprom_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_syseeprom_size);
+ g_syseeprom_drv = drv;
+
+ ret = syseeprom_create_eeprom_attrs();
+ if (ret < 0) {
+ SWITCH_ERR("create syseeprom attributes failed, ret: %d\n", ret);
+ g_syseeprom_drv = NULL;
+ return ret;
+ }
+ SWITCH_INFO("s3ip_sysfs_syseeprom_drivers_register success.\n");
+ return 0;
+}
+
+void s3ip_sysfs_syseeprom_drivers_unregister(void)
+{
+ if (g_syseeprom_drv) {
+ syseeprom_remove_eeprom_attrs();
+ g_syseeprom_drv = NULL;
+ SWITCH_DBG("s3ip_sysfs_syseeprom_drivers_unregister success.\n");
+ }
+
+ return;
+}
+
+struct switch_obj *switch_kobject_create(const char *name, struct kobject *parent)
+{
+ struct switch_obj *obj;
+ int ret;
+
+ obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj) {
+ SWITCH_DBG("switch_kobject_create %s kzalloc error", name);
+ return NULL;
+ }
+
+ obj->kobj.kset = switch_kset;
+
+ ret = kobject_init_and_add(&obj->kobj, &switch_ktype, parent, "%s", name);
+ if (ret) {
+ kobject_put(&obj->kobj);
+ SWITCH_DBG("kobject_init_and_add %s error", name);
+ return NULL;
+ }
+
+ return obj;
+}
+
+void switch_kobject_delete(struct switch_obj **obj)
+{
+ if (*obj) {
+ SWITCH_DBG("%s delete %s.\n", (*obj)->kobj.parent->name, (*obj)->kobj.name);
+ kobject_put(&((*obj)->kobj));
+ *obj = NULL;
+ }
+}
+
+static int __init switch_init(void)
+{
+ SWITCH_INFO("switch_init...\n");
+
+ switch_kset = kset_create_and_add("s3ip", NULL, NULL);
+ if (!switch_kset) {
+ SWITCH_ERR("create switch_kset error.\n");
+ return -ENOMEM;
+ }
+
+ SWITCH_INFO("switch_init success.\n");
+ return 0;
+}
+
+static void __exit switch_exit(void)
+{
+ if (switch_kset) {
+ kset_unregister(switch_kset);
+ }
+
+ SWITCH_INFO("switch_exit success.\n");
+}
+
+module_init(switch_init);
+module_exit(switch_exit);
+EXPORT_SYMBOL(s3ip_sysfs_syseeprom_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_syseeprom_drivers_unregister);
+module_param(g_switch_loglevel, int, 0644);
+MODULE_PARM_DESC(g_switch_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("sonic S3IP sysfs");
+MODULE_DESCRIPTION("switch driver");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/sysled_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/sysled_sysfs.c
new file mode 100644
index 000000000000..242fb20a8755
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/sysled_sysfs.c
@@ -0,0 +1,289 @@
+/*
+ * An sysled_sysfs driver for sysled sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "sysled_sysfs.h"
+
+static int g_sysled_loglevel = 0;
+
+#define SYSLED_INFO(fmt, args...) do { \
+ if (g_sysled_loglevel & INFO) { \
+ printk(KERN_INFO "[SYSLED_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SYSLED_ERR(fmt, args...) do { \
+ if (g_sysled_loglevel & ERR) { \
+ printk(KERN_ERR "[SYSLED_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SYSLED_DBG(fmt, args...) do { \
+ if (g_sysled_loglevel & DBG) { \
+ printk(KERN_DEBUG "[SYSLED_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+static struct switch_obj *g_sysled_obj = NULL;
+static struct s3ip_sysfs_sysled_drivers_s *g_sysled_drv = NULL;
+
+static ssize_t sys_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->get_sys_led_status);
+
+ return g_sysled_drv->get_sys_led_status(buf, PAGE_SIZE);
+}
+
+static ssize_t sys_led_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->set_sys_led_status);
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret != 0) {
+ SYSLED_ERR("invaild led status ret: %d, can't set sys led status\n", ret);
+ SYSLED_ERR("invaild led status buf: %s\n", buf);
+ return -EINVAL;
+ }
+ ret = g_sysled_drv->set_sys_led_status(value);
+ if (ret < 0) {
+ SYSLED_ERR("set sys led status %d faield, ret: %d\n", value, ret);
+ return ret;
+ }
+ SYSLED_DBG("set sys led status %d success\n", value);
+ return count;
+}
+
+static ssize_t bmc_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->get_bmc_led_status);
+
+ return g_sysled_drv->get_bmc_led_status(buf, PAGE_SIZE);
+}
+
+static ssize_t bmc_led_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->set_bmc_led_status);
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret != 0) {
+ SYSLED_ERR("invaild led status ret: %d, can't set bmc led status\n", ret);
+ SYSLED_ERR("invaild led status buf: %s\n", buf);
+ return -EINVAL;
+ }
+ ret = g_sysled_drv->set_bmc_led_status(value);
+ if (ret < 0) {
+ SYSLED_ERR("set bmc led status %d faield, ret: %d\n", value, ret);
+ return ret;
+ }
+ SYSLED_DBG("set bmc led status %d success\n", value);
+ return count;
+}
+
+static ssize_t sys_fan_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->get_sys_fan_led_status);
+
+ return g_sysled_drv->get_sys_fan_led_status(buf, PAGE_SIZE);
+}
+
+static ssize_t sys_fan_led_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->set_sys_fan_led_status);
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret != 0) {
+ SYSLED_ERR("invaild led status ret: %d, can't set sys fan led status\n", ret);
+ SYSLED_ERR("invaild led status buf: %s\n", buf);
+ return -EINVAL;
+ }
+ ret = g_sysled_drv->set_sys_fan_led_status(value);
+ if (ret < 0) {
+ SYSLED_ERR("set sys fan led status %d faield, ret: %d\n", value, ret);
+ return ret;
+ }
+ SYSLED_DBG("set sys fan led status %d success\n", value);
+ return count;
+}
+
+static ssize_t sys_psu_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->get_sys_psu_led_status);
+
+ return g_sysled_drv->get_sys_psu_led_status(buf, PAGE_SIZE);
+}
+
+static ssize_t sys_psu_led_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->set_sys_psu_led_status);
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret != 0) {
+ SYSLED_ERR("invaild led status ret: %d, can't set sys psu led status\n", ret);
+ SYSLED_ERR("invaild led status buf: %s\n", buf);
+ return -EINVAL;
+ }
+ ret = g_sysled_drv->set_sys_psu_led_status(value);
+ if (ret < 0) {
+ SYSLED_ERR("set sys psu led status %d faield, ret: %d\n", value, ret);
+ return ret;
+ }
+ SYSLED_DBG("set sys psu led status %d success\n", value);
+ return count;
+}
+
+static ssize_t id_led_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->get_id_led_status);
+
+ return g_sysled_drv->get_id_led_status(buf, PAGE_SIZE);
+}
+
+static ssize_t id_led_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_sysled_drv);
+ check_p(g_sysled_drv->set_id_led_status);
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret != 0) {
+ SYSLED_ERR("invaild led status ret: %d, can't set id led status\n", ret);
+ SYSLED_ERR("invaild led status buf: %s\n", buf);
+ return -EINVAL;
+ }
+ ret = g_sysled_drv->set_id_led_status(value);
+ if (ret < 0) {
+ SYSLED_ERR("set id led status %d faield, ret: %d\n", value, ret);
+ return ret;
+ }
+ SYSLED_DBG("set id led status %d success\n", value);
+ return count;
+}
+
+/************************************syseeprom dir and attrs*******************************************/
+static struct switch_attribute sys_led_attr = __ATTR(sys_led_status, S_IRUGO | S_IWUSR, sys_led_status_show, sys_led_status_store);
+static struct switch_attribute bmc_led_attr = __ATTR(bmc_led_status, S_IRUGO | S_IWUSR, bmc_led_status_show, bmc_led_status_store);
+static struct switch_attribute fan_led_attr = __ATTR(fan_led_status, S_IRUGO | S_IWUSR, sys_fan_led_status_show, sys_fan_led_status_store);
+static struct switch_attribute psu_led_attr = __ATTR(psu_led_status, S_IRUGO | S_IWUSR, sys_psu_led_status_show, sys_psu_led_status_store);
+static struct switch_attribute id_led_attr = __ATTR(id_led_status, S_IRUGO | S_IWUSR, id_led_status_show, id_led_status_store);
+
+static struct attribute *sysled_dir_attrs[] = {
+ &sys_led_attr.attr,
+ &bmc_led_attr.attr,
+ &fan_led_attr.attr,
+ &psu_led_attr.attr,
+ &id_led_attr.attr,
+ NULL,
+};
+
+static struct attribute_group sysled_attr_group = {
+ .attrs = sysled_dir_attrs,
+};
+
+/* create syseled directory and attributes*/
+static int sysled_root_create(void)
+{
+ g_sysled_obj = switch_kobject_create("sysled", NULL);
+ if (!g_sysled_obj) {
+ SYSLED_ERR("switch_kobject_create sysled error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_sysled_obj->kobj, &sysled_attr_group) != 0) {
+ switch_kobject_delete(&g_sysled_obj);
+ SYSLED_ERR("create sysled dir attrs error!\n");
+ return -EBADRQC;
+ }
+
+ return 0;
+}
+
+/* delete syseled directory and attributes*/
+static void sysled_root_remove(void)
+{
+ if (g_sysled_obj) {
+ sysfs_remove_group(&g_sysled_obj->kobj, &sysled_attr_group);
+ switch_kobject_delete(&g_sysled_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_sysled_drivers_register(struct s3ip_sysfs_sysled_drivers_s *drv)
+{
+ int ret;
+
+ SYSLED_INFO("s3ip_sysfs_sysled_drivers_register...\n");
+ if (g_sysled_drv) {
+ SYSLED_ERR("g_sysled_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ g_sysled_drv = drv;
+
+ ret = sysled_root_create();
+ if (ret < 0) {
+ SYSLED_ERR("sysled create error.\n");
+ g_sysled_drv = NULL;
+ return ret;
+ }
+ SYSLED_INFO("s3ip_sysfs_sysled_drivers_register success\n");
+ return 0;
+}
+
+void s3ip_sysfs_sysled_drivers_unregister(void)
+{
+ if (g_sysled_drv) {
+ sysled_root_remove();
+ g_sysled_drv = NULL;
+ SYSLED_DBG("s3ip_sysfs_sysled_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_sysled_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_sysled_drivers_unregister);
+module_param(g_sysled_loglevel, int, 0644);
+MODULE_PARM_DESC(g_sysled_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/system_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/system_sysfs.c
new file mode 100644
index 000000000000..dd1c3e859a1a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/system_sysfs.c
@@ -0,0 +1,218 @@
+/*
+ * An system_sysfs driver for system sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "system_sysfs.h"
+#include "switch_driver.h"
+
+static int g_system_loglevel = 0;
+
+#define SYSTEM_INFO(fmt, args...) do { \
+ if (g_system_loglevel & INFO) { \
+ printk(KERN_INFO "[system][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SYSTEM_ERR(fmt, args...) do { \
+ if (g_system_loglevel & ERR) { \
+ printk(KERN_ERR "[system][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SYSTEM_DBG(fmt, args...) do { \
+ if (g_system_loglevel & DBG) { \
+ printk(KERN_DEBUG "[system][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct system_obj_s {
+ struct switch_obj *obj;
+};
+
+struct system_s {
+ unsigned int api_number;
+ struct system_obj_s *temp;
+};
+
+static struct s3ip_sysfs_system_drivers_s *g_system_drv = NULL;
+static struct switch_obj *g_system_obj = NULL;
+
+static ssize_t system_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ int value;
+ struct switch_device_attribute *system_attr;
+
+ check_p(g_system_drv);
+ check_p(g_system_drv->get_system_value);
+
+ system_attr = to_switch_device_attr(attr);
+ check_p(system_attr);
+ SYSTEM_DBG("system_value_show type 0x%x \n", system_attr->type);
+ return g_system_drv->get_system_value(system_attr->type, &value, buf, PAGE_SIZE);
+}
+
+static ssize_t system_value_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ int ret, value;
+ struct switch_device_attribute *system_attr;
+
+ check_p(g_system_drv);
+ check_p(g_system_drv->set_system_value);
+
+ system_attr = to_switch_device_attr(attr);
+ check_p(system_attr);
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret) {
+ SYSTEM_ERR("system_value_store, input parameter: %s error. ret:%d\n", buf, ret);
+ return ret;
+ }
+
+ if(value > 0xff) {
+ SYSTEM_ERR("system_value_store, input parameter bigger than 0xff: %d\n", value);
+ return -EINVAL;
+ }
+ SYSTEM_DBG("system_value_store, type: 0x%x. value=%d\n", system_attr->type, value);
+ ret = g_system_drv->set_system_value(system_attr->type, value);
+ if (ret < 0) {
+ /* ret=-999 if not support */
+ SYSTEM_ERR("set system reg value: %d failed. ret:%d\n", value, ret);
+ return ret;
+ }
+ return count;
+}
+
+static ssize_t system_port_port_status_value(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ struct switch_device_attribute *system_attr;
+
+ check_p(g_system_drv);
+ check_p(g_system_drv->get_system_port_power_status);
+
+ system_attr = to_switch_device_attr(attr);
+ check_p(system_attr);
+ SYSTEM_DBG("type 0x%x \n", system_attr->type);
+ return g_system_drv->get_system_port_power_status(system_attr->type, buf, PAGE_SIZE);
+}
+
+/************************************system dir and attrs*******************************************/
+static SWITCH_DEVICE_ATTR(bmc_ready, S_IRUGO | S_IWUSR, system_value_show, system_value_store, WB_SYSTEM_BMC_READY);
+static SWITCH_DEVICE_ATTR(sol_active, S_IRUGO | S_IWUSR, system_value_show, system_value_store, WB_SYSTEM_SOL_ACTIVE);
+static SWITCH_DEVICE_ATTR(psu_reset, S_IWUSR, NULL, system_value_store, WB_SYSTEM_PSU_RESET);
+static SWITCH_DEVICE_ATTR(cpu_board_ctrl, S_IWUSR, NULL, system_value_store, WB_SYSTEM_CPU_BOARD_CTRL);
+static SWITCH_DEVICE_ATTR(cpu_board_status, S_IRUGO , system_value_show, NULL, WB_SYSTEM_CPU_BOARD_STATUS);
+static SWITCH_DEVICE_ATTR(bios_switch, S_IWUSR, NULL, system_value_store, WB_SYSTEM_BIOS_SWITCH);
+static SWITCH_DEVICE_ATTR(bios_view, S_IRUGO, system_value_show, NULL, WB_SYSTEM_BIOS_VIEW);
+static SWITCH_DEVICE_ATTR(bios_boot_ok, S_IRUGO, system_value_show, NULL, WB_SYSTEM_BIOS_BOOT_OK);
+static SWITCH_DEVICE_ATTR(bios_fail_record, S_IRUGO, system_value_show, NULL, WB_SYSTEM_BIOS_FAIL_RECORD);
+static SWITCH_DEVICE_ATTR(bmc_reset, S_IWUSR, NULL, system_value_store, WB_SYSTEM_BMC_RESET);
+static SWITCH_DEVICE_ATTR(mac_board_reset, S_IRUGO | S_IWUSR, system_value_show, system_value_store, WB_SYSTEM_MAC_BOARD_RESET);
+static SWITCH_DEVICE_ATTR(mac_pwr_ctrl, S_IRUGO | S_IWUSR, system_value_show, system_value_store, WB_SYSTEM_MAC_PWR_CTRL);
+static SWITCH_DEVICE_ATTR(emmc_pwr_ctrl, S_IRUGO | S_IWUSR, system_value_show, system_value_store, WB_SYSTEM_EMMC_PWR_CTRL);
+static SWITCH_DEVICE_ATTR(port_pwr_ctl, S_IRUGO | S_IWUSR, system_port_port_status_value, system_value_store, WB_SYSTEM_PORT_PWR_CTL);
+static SWITCH_DEVICE_ATTR(bmc_view, S_IRUGO, system_value_show, NULL, WB_SYSTEM_BMC_VIEW);
+static SWITCH_DEVICE_ATTR(bmc_switch, S_IWUSR, NULL, system_value_store, WB_SYSTEM_BMC_SWITCH);
+
+static struct attribute *system_dir_attrs[] = {
+ &switch_dev_attr_bmc_ready.switch_attr.attr,
+ &switch_dev_attr_sol_active.switch_attr.attr,
+ &switch_dev_attr_psu_reset.switch_attr.attr,
+ &switch_dev_attr_cpu_board_ctrl.switch_attr.attr,
+ &switch_dev_attr_cpu_board_status.switch_attr.attr,
+ &switch_dev_attr_bios_switch.switch_attr.attr,
+ &switch_dev_attr_bios_view.switch_attr.attr,
+ &switch_dev_attr_bios_boot_ok.switch_attr.attr,
+ &switch_dev_attr_bios_fail_record.switch_attr.attr,
+ &switch_dev_attr_bmc_reset.switch_attr.attr,
+ &switch_dev_attr_mac_board_reset.switch_attr.attr,
+ &switch_dev_attr_mac_pwr_ctrl.switch_attr.attr,
+ &switch_dev_attr_emmc_pwr_ctrl.switch_attr.attr,
+ &switch_dev_attr_port_pwr_ctl.switch_attr.attr,
+ &switch_dev_attr_bmc_view.switch_attr.attr,
+ &switch_dev_attr_bmc_switch.switch_attr.attr,
+ NULL,
+};
+
+static struct attribute_group system_root_attr_group = {
+ .attrs = system_dir_attrs,
+};
+
+/* create system directory and number attributes */
+static int system_root_create(void)
+{
+ g_system_obj = switch_kobject_create("system", NULL);
+ if (!g_system_obj) {
+ SYSTEM_ERR("switch_kobject_create system error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_system_obj->kobj, &system_root_attr_group) != 0) {
+ switch_kobject_delete(&g_system_obj);
+ SYSTEM_ERR("create system dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete system directory and number attributes */
+static void system_root_remove(void)
+{
+ if (g_system_obj) {
+ sysfs_remove_group(&g_system_obj->kobj, &system_root_attr_group);
+ switch_kobject_delete(&g_system_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_system_drivers_register(struct s3ip_sysfs_system_drivers_s *drv)
+{
+ int ret;
+
+ SYSTEM_INFO("s3ip_sysfs_system_drivers_register...\n");
+ check_p(drv);
+ g_system_drv = drv;
+ ret = system_root_create();
+ if (ret < 0) {
+ SYSTEM_ERR("create system root dir and attrs failed, ret: %d\n", ret);
+ return ret;
+ }
+
+ SYSTEM_INFO("s3ip_sysfs_system_drivers_register success\n");
+ return ret;
+}
+
+void s3ip_sysfs_system_drivers_unregister(void)
+{
+ if (g_system_drv) {
+ system_root_remove();
+ g_system_drv = NULL;
+ SYSTEM_DBG("s3ip_sysfs_system_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_system_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_system_drivers_unregister);
+module_param(g_system_loglevel, int, 0644);
+MODULE_PARM_DESC(g_system_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/temp_sensor_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/temp_sensor_sysfs.c
new file mode 100644
index 000000000000..bfda43b47973
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/temp_sensor_sysfs.c
@@ -0,0 +1,458 @@
+/*
+ * An temp_sensor_sysfs driver for temperature sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "temp_sensor_sysfs.h"
+
+static int g_temp_sensor_loglevel = 0;
+
+#define TEMP_SENSOR_INFO(fmt, args...) do { \
+ if (g_temp_sensor_loglevel & INFO) { \
+ printk(KERN_INFO "[TEMP_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define TEMP_SENSOR_ERR(fmt, args...) do { \
+ if (g_temp_sensor_loglevel & ERR) { \
+ printk(KERN_ERR "[TEMP_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define TEMP_SENSOR_DBG(fmt, args...) do { \
+ if (g_temp_sensor_loglevel & DBG) { \
+ printk(KERN_DEBUG "[TEMP_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct temp_sensor_obj_s {
+ struct switch_obj *obj;
+};
+
+struct temp_sensor_s {
+ unsigned int temp_number;
+ struct temp_sensor_obj_s *temp;
+};
+
+static struct s3ip_sysfs_temp_sensor_drivers_s *g_temp_sensor_drv = NULL;
+static struct temp_sensor_s g_temp_sensor;
+static struct switch_obj *g_temp_sensor_obj = NULL;
+
+static ssize_t temp_sensor_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_temp_sensor.temp_number);
+}
+
+static ssize_t temp_sensor_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_value);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_value(temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t temp_sensor_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_alias);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_alias(temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t temp_sensor_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_type);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_type(temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t temp_sensor_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_max);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_max(temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t temp_sensor_max_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int temp_index;
+ int ret;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->set_main_board_temp_max);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ ret = g_temp_sensor_drv->set_main_board_temp_max(temp_index, buf, count);
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("set temp%u max threshold failed, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return ret;
+ }
+ TEMP_SENSOR_DBG("set temp%u max threshold success, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t temp_sensor_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_min);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_min(temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t temp_sensor_min_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int temp_index;
+ int ret;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->set_main_board_temp_min);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ ret = g_temp_sensor_drv->set_main_board_temp_min(temp_index, buf, count);
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("set temp%u min threshold failed, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return ret;
+ }
+ TEMP_SENSOR_DBG("set temp%u min threshold success, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t temp_sensor_high_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_high);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_high(temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t temp_sensor_high_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int temp_index;
+ int ret;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->set_main_board_temp_high);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ ret = g_temp_sensor_drv->set_main_board_temp_high(temp_index, buf, count);
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("set temp%u high threshold failed, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return ret;
+ }
+ TEMP_SENSOR_DBG("set temp%u high threshold success, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t temp_sensor_low_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_low);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_low(temp_index, buf, PAGE_SIZE);
+}
+
+static ssize_t temp_sensor_low_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int temp_index;
+ int ret;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->set_main_board_temp_low);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ ret = g_temp_sensor_drv->set_main_board_temp_low(temp_index, buf, count);
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("set temp%u low threshold failed, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return ret;
+ }
+ TEMP_SENSOR_DBG("set temp%u low threshold success, value: %s, count: %lu, ret: %d\n",
+ temp_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t temp_sensor_monitor_flag_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int temp_index;
+
+ check_p(g_temp_sensor_drv);
+ check_p(g_temp_sensor_drv->get_main_board_temp_monitor_flag);
+
+ temp_index = obj->index;
+ TEMP_SENSOR_DBG("temp index: %u\n", temp_index);
+ return g_temp_sensor_drv->get_main_board_temp_monitor_flag(temp_index, buf, PAGE_SIZE);
+}
+
+/************************************temp_sensor dir and attrs*******************************************/
+static struct switch_attribute num_temp_att = __ATTR(number, S_IRUGO, temp_sensor_number_show, NULL);
+
+static struct attribute *temp_sensor_dir_attrs[] = {
+ &num_temp_att.attr,
+ NULL,
+};
+
+static struct attribute_group temp_sensor_root_attr_group = {
+ .attrs = temp_sensor_dir_attrs,
+};
+
+/*******************************temp1 temp2 dir and attrs*******************************************/
+static struct switch_attribute temp_value_attr = __ATTR(value, S_IRUGO, temp_sensor_value_show, NULL);
+static struct switch_attribute temp_alias_attr = __ATTR(alias, S_IRUGO, temp_sensor_alias_show, NULL);
+static struct switch_attribute temp_type_attr = __ATTR(type, S_IRUGO, temp_sensor_type_show, NULL);
+static struct switch_attribute temp_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, temp_sensor_max_show, temp_sensor_max_store);
+static struct switch_attribute temp_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, temp_sensor_min_show, temp_sensor_min_store);
+static struct switch_attribute temp_high_attr = __ATTR(high, S_IRUGO | S_IWUSR, temp_sensor_high_show, temp_sensor_high_store);
+static struct switch_attribute temp_low_attr = __ATTR(low, S_IRUGO | S_IWUSR, temp_sensor_low_show, temp_sensor_low_store);
+static struct switch_attribute temp_monitor_flag_attr = __ATTR(monitor_flag, S_IRUGO, temp_sensor_monitor_flag_show, NULL);
+
+static struct attribute *temp_sensor_attrs[] = {
+ &temp_value_attr.attr,
+ &temp_alias_attr.attr,
+ &temp_type_attr.attr,
+ &temp_max_attr.attr,
+ &temp_min_attr.attr,
+ &temp_high_attr.attr,
+ &temp_low_attr.attr,
+ &temp_monitor_flag_attr.attr,
+ NULL,
+};
+
+static struct attribute_group temp_sensor_attr_group = {
+ .attrs = temp_sensor_attrs,
+};
+
+static int temp_sensor_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct temp_sensor_obj_s *temp_sensor;
+
+ temp_sensor = &g_temp_sensor.temp[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "temp%u", index);
+ temp_sensor->obj = switch_kobject_create(name, parent);
+ if (!temp_sensor->obj) {
+ TEMP_SENSOR_ERR("create %s object error.\n", name);
+ return -ENOMEM;
+ }
+ temp_sensor->obj->index = index;
+ if (sysfs_create_group(&temp_sensor->obj->kobj, &temp_sensor_attr_group) != 0) {
+ TEMP_SENSOR_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&temp_sensor->obj);
+ return -EBADRQC;
+ }
+ TEMP_SENSOR_DBG("create %s dir and attrs success.\n", name);
+ return 0;
+}
+
+static void temp_sensor_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct temp_sensor_obj_s *temp_sensor;
+
+ temp_sensor = &g_temp_sensor.temp[index - 1];
+ if (temp_sensor->obj) {
+ sysfs_remove_group(&temp_sensor->obj->kobj, &temp_sensor_attr_group);
+ switch_kobject_delete(&temp_sensor->obj);
+ TEMP_SENSOR_DBG("delete temp%u dir and attrs success.\n", index);
+ }
+
+ return;
+}
+
+static int temp_sensor_sub_create_kobj_and_attrs(struct kobject *parent, int temp_num)
+{
+ unsigned int temp_index, i;
+
+ g_temp_sensor.temp = kzalloc(sizeof(struct temp_sensor_obj_s) * temp_num, GFP_KERNEL);
+ if (!g_temp_sensor.temp) {
+ TEMP_SENSOR_ERR("kzalloc g_temp_sensor.temp error, temp number: %d.\n", temp_num);
+ return -ENOMEM;
+ }
+
+ for (temp_index = 1; temp_index <= temp_num; temp_index++) {
+ if (temp_sensor_sub_single_create_kobj_and_attrs(parent, temp_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = temp_index; i > 0; i--) {
+ temp_sensor_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_temp_sensor.temp);
+ g_temp_sensor.temp = NULL;
+ return -EBADRQC;
+}
+
+/* create temp[1-n] directory and attributes*/
+static int temp_sensor_sub_create(void)
+{
+ int ret;
+
+ ret = temp_sensor_sub_create_kobj_and_attrs(&g_temp_sensor_obj->kobj,
+ g_temp_sensor.temp_number);
+ return ret;
+}
+
+/* delete temp[1-n] directory and attributes*/
+static void temp_sensor_sub_remove(void)
+{
+ unsigned int temp_index;
+
+ if (g_temp_sensor.temp) {
+ for (temp_index = g_temp_sensor.temp_number; temp_index > 0; temp_index--) {
+ temp_sensor_sub_single_remove_kobj_and_attrs(temp_index);
+ }
+ kfree(g_temp_sensor.temp);
+ g_temp_sensor.temp = NULL;
+ }
+
+ return;
+}
+
+/* create temp_sensor directory and number attributes */
+static int temp_sensor_root_create(void)
+{
+ g_temp_sensor_obj = switch_kobject_create("temp_sensor", NULL);
+ if (!g_temp_sensor_obj) {
+ TEMP_SENSOR_ERR("switch_kobject_create temp_sensor error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_temp_sensor_obj->kobj, &temp_sensor_root_attr_group) != 0) {
+ switch_kobject_delete(&g_temp_sensor_obj);
+ TEMP_SENSOR_ERR("create temp_sensor dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete temp_sensor directory and number attributes */
+static void temp_sensor_root_remove(void)
+{
+ if (g_temp_sensor_obj) {
+ sysfs_remove_group(&g_temp_sensor_obj->kobj, &temp_sensor_root_attr_group);
+ switch_kobject_delete(&g_temp_sensor_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_temp_sensor_drivers_register(struct s3ip_sysfs_temp_sensor_drivers_s *drv)
+{
+ int ret, temp_num;
+
+ TEMP_SENSOR_INFO("s3ip_sysfs_temp_sensor_drivers_register...\n");
+ if (g_temp_sensor_drv) {
+ TEMP_SENSOR_ERR("g_temp_sensor_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_main_board_temp_number);
+ g_temp_sensor_drv = drv;
+
+ temp_num = g_temp_sensor_drv->get_main_board_temp_number();
+ if (temp_num <= 0) {
+ TEMP_SENSOR_ERR("temp sensor number: %d, don't need to create temp_sensor dirs and attrs.\n",
+ temp_num);
+ g_temp_sensor_drv = NULL;
+ return -EINVAL;
+ }
+ mem_clear(&g_temp_sensor, sizeof(struct temp_sensor_s));
+ g_temp_sensor.temp_number = temp_num;
+ ret = temp_sensor_root_create();
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("create temp_sensor root dir and attrs failed, ret: %d\n", ret);
+ g_temp_sensor_drv = NULL;
+ return ret;
+ }
+
+ ret = temp_sensor_sub_create();
+ if (ret < 0) {
+ TEMP_SENSOR_ERR("create temp_sensor sub dir and attrs failed, ret: %d\n", ret);
+ temp_sensor_root_remove();
+ g_temp_sensor_drv = NULL;
+ return ret;
+ }
+ TEMP_SENSOR_INFO("s3ip_sysfs_temp_sensor_drivers_register success\n");
+ return ret;
+}
+
+void s3ip_sysfs_temp_sensor_drivers_unregister(void)
+{
+ if (g_temp_sensor_drv) {
+ temp_sensor_sub_remove();
+ temp_sensor_root_remove();
+ g_temp_sensor_drv = NULL;
+ TEMP_SENSOR_DBG("s3ip_sysfs_temp_sensor_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_temp_sensor_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_temp_sensor_drivers_unregister);
+module_param(g_temp_sensor_loglevel, int, 0644);
+MODULE_PARM_DESC(g_temp_sensor_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/transceiver_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/transceiver_sysfs.c
new file mode 100644
index 000000000000..6384b452186c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/transceiver_sysfs.c
@@ -0,0 +1,996 @@
+/*
+ * An transceiver_sysfs driver for transceiver sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "transceiver_sysfs.h"
+
+static int g_sff_loglevel = 0;
+static bool g_sff_present_debug = 0;
+
+#define WB_QSFP_TX_FAULT_OFFSET (4)
+#define WB_QSFPDD_TX_FAULT_OFFSET (17*128 + 135)
+#define WB_QSFP_TX_DISABLE_OFFSET (86)
+#define WB_QSFPDD_TX_DISABLE_OFFSET (16*128 + 130)
+#define WB_QSFP_RX_LOS_OFFSET (3)
+#define WB_QSFPDD_RX_LOS_OFFSET (17*128 + 147)
+#define WB_QSFP_LP_MODE_OFFSET (93)
+#define WB_QSFPDD_LP_MODE_OFFSET (26)
+
+#define SFF_INFO(fmt, args...) do { \
+ if (g_sff_loglevel & INFO) { \
+ printk(KERN_INFO "[SFF_SYSFS][func:%s line:%d]"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SFF_ERR(fmt, args...) do { \
+ if (g_sff_loglevel & ERR) { \
+ printk(KERN_ERR "[SFF_SYSFS][func:%s line:%d]"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define SFF_DBG(fmt, args...) do { \
+ if (g_sff_loglevel & DBG) { \
+ printk(KERN_DEBUG "[SFF_SYSFS][func:%s line:%d]"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct sff_obj_s {
+ struct switch_obj *sff_obj;
+ struct bin_attribute bin;
+ int sff_creat_bin_flag;
+};
+
+struct sff_s {
+ unsigned int sff_number;
+ struct sff_obj_s *sff;
+};
+
+static struct sff_s g_sff;
+static struct switch_obj *g_sff_obj = NULL;
+static struct s3ip_sysfs_transceiver_drivers_s *g_sff_drv = NULL;
+
+static ssize_t transceiver_power_on_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->get_transceiver_power_on_status);
+
+ return g_sff_drv->get_transceiver_power_on_status(buf, PAGE_SIZE);
+}
+
+static ssize_t transceiver_power_on_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int eth_index, eth_num;
+ int ret, value;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->set_eth_power_on_status);
+
+ sscanf(buf, "%d", &value);
+ if (value < 0 || value > 1) {
+ SFF_ERR("invalid value: %d, can't set power on status.\n", value);
+ return -EINVAL;
+ }
+
+ eth_num = g_sff.sff_number;
+ for (eth_index = 1; eth_index <= eth_num; eth_index++) {
+ SFF_DBG("eth index: %u\n", eth_index);
+ ret = g_sff_drv->set_eth_power_on_status(eth_index, value);
+ if (ret < 0) {
+ SFF_ERR("set eth%u power status failed, ret: %d\n", eth_index, ret);
+ break;
+ }
+ }
+ SFF_DBG("transceiver_power_on_store ok. sff num:%d, len:%d\n", eth_num, ret);
+ return count;
+}
+
+static ssize_t transceiver_number_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", g_sff.sff_number);
+}
+
+static ssize_t eth_optoe_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int sff_index;
+ int optoe_type;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->get_eth_optoe_type);
+
+ sff_index = obj->index;
+ SFF_DBG("eth_optoe_type_show, sff index:%u\n", sff_index);
+ return g_sff_drv->get_eth_optoe_type(sff_index, &optoe_type, buf, PAGE_SIZE);
+}
+
+static ssize_t eth_optoe_type_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int sff_index;
+ int ret;
+ int optoe_type;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->set_eth_optoe_type);
+
+ ret = kstrtoint(buf, 0, &optoe_type);
+ if (ret != 0) {
+ SFF_ERR("invaild optoe_type ret: %d, buf: %s.\n", ret, buf);
+ return -EINVAL;
+ }
+
+ sff_index = obj->index;
+ SFF_DBG("eth_optoe_type_store, sff index:%u, optoe_type:%d\n", sff_index, optoe_type);
+ ret = g_sff_drv->set_eth_optoe_type(sff_index, optoe_type);
+ if(ret < 0) {
+ SFF_ERR("set_eth_optoe_type error. sff index:%u, ret:%d\n", sff_index, ret);
+ return ret;
+ }
+
+ SFF_DBG("eth_optoe_type_store ok. sff index:%u, optoe_type:%d\n", sff_index, optoe_type);
+ return count;
+}
+
+
+static ssize_t transceiver_present_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->get_transceiver_present_status);
+
+ return g_sff_drv->get_transceiver_present_status(buf, PAGE_SIZE);
+}
+
+static ssize_t eth_power_on_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eth_index;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->get_eth_power_on_status);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ return g_sff_drv->get_eth_power_on_status(eth_index, buf, PAGE_SIZE);
+}
+
+static ssize_t eth_power_on_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int eth_index;
+ int ret, value;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->set_eth_power_on_status);
+
+ sscanf(buf, "%d", &value);
+ eth_index = obj->index;
+ if (value < 0 || value > 1) {
+ SFF_ERR("invalid value: %d, can't set eth%u power on status.\n", value, eth_index);
+ return -EINVAL;
+ }
+
+ ret = g_sff_drv->set_eth_power_on_status(eth_index, value);
+ if (ret < 0) {
+ SFF_ERR("set eth%u power on status %d failed, ret: %d\n", eth_index, value, ret);
+ return ret;
+ }
+ SFF_DBG("set eth%u power on status %d success\n", eth_index, value);
+ return count;
+}
+
+static ssize_t eth_tx_fault_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eth_index;
+ int ret;
+ char module_type[1], value[1];
+ loff_t offset;
+ char mask;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->read_eth_eeprom_data);
+ check_p(g_sff_drv->get_eth_tx_fault_status);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ mem_clear(module_type, sizeof(module_type));
+ mem_clear(value, sizeof(value));
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, module_type, 0, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module type failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if (module_type[0] == 0x03) {
+ SFF_DBG("get eth%u module type is SFP\n", eth_index);
+ return g_sff_drv->get_eth_tx_fault_status(eth_index, buf, PAGE_SIZE);
+ } else {
+ if ((module_type[0] == 0x11) || (module_type[0] == 0x0D)) {
+ SFF_DBG("get eth%u module type is QSFP\n", eth_index);
+ offset = WB_QSFP_TX_FAULT_OFFSET;
+ mask = 0xf;
+ } else if ((module_type[0] == 0x18) || (module_type[0] == 0x1e)) {
+ SFF_DBG("get eth%u module type is QSFP-DD\n", eth_index);
+ offset = WB_QSFPDD_TX_FAULT_OFFSET;
+ mask = 0xff;
+ } else {
+ SFF_ERR("eth%u module is unknown, module_type:%d\n", eth_index, module_type[0]);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, value, offset, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module tx fault value failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if ((value[0] & mask) != 0) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 1);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 0);
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t eth_tx_disable_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ unsigned int eth_index;
+ int ret;
+ char module_type[1], value[1];
+ loff_t offset;
+ char mask;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->read_eth_eeprom_data);
+ check_p(g_sff_drv->get_eth_tx_disable_status);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ mem_clear(module_type, sizeof(module_type));
+ mem_clear(value, sizeof(value));
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, module_type, 0, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module type failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if (module_type[0] == 0x03) {
+ SFF_DBG("get eth%u module type is SFP\n", eth_index);
+ return g_sff_drv->get_eth_tx_disable_status(eth_index, buf, PAGE_SIZE);
+ } else {
+ if ((module_type[0] == 0x11) || (module_type[0] == 0x0D)) {
+ SFF_DBG("get eth%u module type is QSFP\n", eth_index);
+ offset = WB_QSFP_TX_DISABLE_OFFSET;
+ mask = 0xf;
+ } else if ((module_type[0] == 0x18) || (module_type[0] == 0x1e)) {
+ SFF_DBG("get eth%u module type is QSFP-DD\n", eth_index);
+ offset = WB_QSFPDD_TX_DISABLE_OFFSET;
+ mask = 0xff;
+ } else {
+ SFF_ERR("eth%u module is unknown, module_type:%d\n", eth_index, module_type[0]);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, value, offset, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module tx disable value failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if ((value[0] & mask) != 0) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 1);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 0);
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t eth_tx_disable_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int eth_index;
+ int ret, value;
+ char module_type[1], write_buf[1];
+ loff_t offset;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->read_eth_eeprom_data);
+ check_p(g_sff_drv->write_eth_eeprom_data);
+ check_p(g_sff_drv->set_eth_tx_disable_status);
+
+ sscanf(buf, "%d", &value);
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u, tx_disable:0x%x\n", eth_index, value);
+
+ if (value < 0 || value > 1) {
+ SFF_ERR("invalid value: %d, can't set eth%u tx disable status.\n", value, eth_index);
+ }
+
+ write_buf[0] = 0;
+ mem_clear(module_type, sizeof(module_type));
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, module_type, 0, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module type failed, ret: %d\n", eth_index, ret);
+ return ret;
+ }
+
+ if (module_type[0] == 0x03) {
+ SFF_DBG("get eth%u module type is SFP\n", eth_index);
+
+ ret = g_sff_drv->set_eth_tx_disable_status(eth_index, value);
+ if (ret < 0) {
+ SFF_ERR("set eth%u tx disable status %d failed, ret: %d\n", eth_index, value, ret);
+ return ret;
+ }
+ } else {
+ if ((module_type[0] == 0x11) || (module_type[0] == 0x0D)) {
+ SFF_DBG("get eth%u module type is QSFP\n", eth_index);
+ offset = WB_QSFP_TX_DISABLE_OFFSET;
+ if (value != 0) {
+ write_buf[0] = 0xf;
+ }
+ } else if ((module_type[0] == 0x18) || (module_type[0] == 0x1e)) {
+ SFF_DBG("get eth%u module type is QSFP-DD\n", eth_index);
+ offset = WB_QSFPDD_TX_DISABLE_OFFSET;
+ if (value != 0) {
+ write_buf[0] = 0xff;
+ }
+ } else {
+ SFF_ERR("eth%u module is unknown, module_type:%d\n", eth_index, module_type[0]);
+ return -EINVAL;
+ }
+
+ ret = g_sff_drv->write_eth_eeprom_data(eth_index, write_buf, offset, 1);
+ if (ret < 0) {
+ SFF_ERR("set eth%u tx disable status %d failed, ret: %d\n", eth_index, value, ret);
+ return ret;
+ }
+ }
+
+ SFF_DBG("set eth%u tx disable status %d success\n", eth_index, value);
+ return count;
+}
+
+static ssize_t eth_present_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eth_index;
+ int ret, res;
+ char debug_file_buf[DEBUG_FILE_SIZE];
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->get_eth_present_status);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ ret = g_sff_drv->get_eth_present_status(eth_index, buf, PAGE_SIZE);
+ if (ret < 0) {
+ SFF_ERR("get eth%u present status failed, ret: %d\n", eth_index, ret);
+ return ret;
+ }
+
+ if (g_sff_present_debug) {
+ SFF_INFO("s3ip sysfs sff present debug is enable\n");
+ if (strcmp(buf, DEV_ABSENT_STR) == 0) {
+ SFF_DBG("eth%d absent, return act value\n", eth_index);
+ return ret;
+ }
+
+ if ((strncmp(buf, SWITCH_DEV_NO_SUPPORT, strlen(SWITCH_DEV_NO_SUPPORT)) == 0) || (strncmp(buf, SWITCH_DEV_ERROR, strlen(SWITCH_DEV_ERROR)) == 0)) {
+ SFF_DBG("eth%d status sysfs unsupport or error\n", eth_index);
+ return ret;
+ }
+
+ mem_clear(debug_file_buf, sizeof(debug_file_buf));
+ res = dev_debug_file_read(SINGLE_TRANSCEIVER_PRESENT_DEBUG_FILE, eth_index, debug_file_buf, sizeof(debug_file_buf));
+ if (res) {
+ SFF_ERR("eth%u present debug file read failed, ret: %d\n", eth_index, res);
+ return ret;
+ }
+
+ if ((strcmp(debug_file_buf, DEV_PRESEN_STR) == 0) || (strcmp(debug_file_buf, DEV_ABSENT_STR) == 0)) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s", debug_file_buf);
+ } else {
+ SFF_ERR("eth%d present debug file value err, value: %s, not 0 or 1\n", eth_index, debug_file_buf);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static ssize_t eth_rx_los_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eth_index;
+ int ret;
+ char module_type[1], value[1];
+ loff_t offset;
+ char mask;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->read_eth_eeprom_data);
+ check_p(g_sff_drv->get_eth_rx_los_status);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ mem_clear(module_type, sizeof(module_type));
+ mem_clear(value, sizeof(value));
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, module_type, 0, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module type failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if (module_type[0] == 0x03) {
+ SFF_DBG("get eth%u module type is SFP\n", eth_index);
+ return g_sff_drv->get_eth_rx_los_status(eth_index, buf, PAGE_SIZE);
+ } else {
+ if ((module_type[0] == 0x11) || (module_type[0] == 0x0D)) {
+ SFF_DBG("get eth%u module type is QSFP\n", eth_index);
+ offset = WB_QSFP_RX_LOS_OFFSET;
+ mask = 0xf;
+ } else if ((module_type[0] == 0x18) || (module_type[0] == 0x1e)) {
+ SFF_DBG("get eth%u module type is QSFP-DD\n", eth_index);
+ offset = WB_QSFPDD_RX_LOS_OFFSET;
+ mask = 0xff;
+ } else {
+ SFF_ERR("eth%u module is unknown, module_type:%d\n", eth_index, module_type[0]);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, value, offset, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module rx los value failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if ((value[0] & mask) != 0) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 1);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 0);
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t eth_reset_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eth_index;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->get_eth_reset_status);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ return g_sff_drv->get_eth_reset_status(eth_index, buf, PAGE_SIZE);
+}
+
+static ssize_t eth_reset_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int eth_index;
+ int ret, value;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->set_eth_reset_status);
+
+ sscanf(buf, "%d", &value);
+ eth_index = obj->index;
+ ret = g_sff_drv->set_eth_reset_status(eth_index, value);
+ if (ret < 0) {
+ SFF_ERR("set eth%u reset status %d failed, ret: %d\n", eth_index, value, ret);
+ return ret;
+ }
+ SFF_DBG("set eth%u reset status %d success\n", eth_index, value);
+ return count;
+}
+
+static ssize_t eth_low_power_mode_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eth_index;
+ int ret;
+ char module_type[1], value[1];
+ loff_t offset;
+ char mask;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->read_eth_eeprom_data);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ mem_clear(module_type, sizeof(module_type));
+ mem_clear(value, sizeof(value));
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, module_type, 0, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module type failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if (module_type[0] == 0x03) {
+ SFF_ERR("eth%u SFP module low power mode no support\n", eth_index);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ if ((module_type[0] == 0x11) || (module_type[0] == 0x0D)) {
+ SFF_DBG("get eth%u module type is QSFP\n", eth_index);
+ offset = WB_QSFP_LP_MODE_OFFSET;
+ mask = 0x3;
+ } else if ((module_type[0] == 0x18) || (module_type[0] == 0x1e)) {
+ SFF_DBG("get eth%u module type is QSFP-DD\n", eth_index);
+ offset = WB_QSFPDD_LP_MODE_OFFSET;
+ mask = 0x10;
+ } else {
+ SFF_ERR("eth%u module is unknown, module_type:%d\n", eth_index, module_type[0]);
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, value, offset, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module lp mode value failed, ret: %d\n", eth_index, ret);
+ if (ret == -WB_SYSFS_RV_UNSUPPORT) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_NO_SUPPORT);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%s\n", SWITCH_DEV_ERROR);
+ }
+ }
+
+ if ((value[0] & mask) == mask) {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 1);
+ } else {
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%d\n", 0);
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t eth_low_power_mode_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int eth_index;
+ int ret, value;
+ char module_type[1], tmp_v[1];
+ loff_t offset;
+ unsigned char mask;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->read_eth_eeprom_data);
+ check_p(g_sff_drv->write_eth_eeprom_data);
+
+ sscanf(buf, "%d", &value);
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ if (value < 0 || value > 1) {
+ SFF_ERR("invalid value: %d, can't set eth%u lp mode status.\n", value, eth_index);
+ return -EINVAL;
+ }
+
+ mask = 0;
+ mem_clear(module_type, sizeof(module_type));
+ mem_clear(tmp_v, sizeof(tmp_v));
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, module_type, 0, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module type failed, ret: %d\n", eth_index, ret);
+ return ret;
+ }
+ SFF_DBG("module type:0x%x\n", module_type[0]);
+
+ if (module_type[0] == 0x03) {
+ SFF_ERR("eth%u SFP module low power mode no support\n", eth_index);
+ return -WB_SYSFS_RV_UNSUPPORT;
+ } else {
+ if ((module_type[0] == 0x11) || (module_type[0] == 0x0D)) {
+ SFF_DBG("get eth%u module type is QSFP\n", eth_index);
+ offset = WB_QSFP_LP_MODE_OFFSET;
+ mask = 0x3;
+ } else if ((module_type[0] == 0x18) || (module_type[0] == 0x1e)) {
+ SFF_DBG("get eth%u module type is QSFP-DD\n", eth_index);
+ offset = WB_QSFPDD_LP_MODE_OFFSET;
+ mask = 0x10;
+ } else {
+ SFF_ERR("eth%u module is unknown, module_type:%d\n", eth_index, module_type[0]);
+ return -EINVAL;
+ }
+
+ ret = g_sff_drv->read_eth_eeprom_data(eth_index, tmp_v, offset, 1);
+ if (ret < 0) {
+ SFF_ERR("get eth%u module lp mode value failed, ret: %d\n", eth_index, ret);
+ return ret;
+ }
+
+ if (value == 1) {
+ tmp_v[0] = tmp_v[0] | mask;
+ } else {
+ tmp_v[0] = tmp_v[0] & (~mask);
+ }
+
+ ret = g_sff_drv->write_eth_eeprom_data(eth_index, tmp_v, offset, 1);
+ if (ret < 0) {
+ SFF_ERR("set eth%u module lp mode value failed, ret: %d\n", eth_index, ret);
+ return -EIO;
+ }
+ }
+
+ return count;
+}
+
+static ssize_t eth_interrupt_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int eth_index;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->get_eth_interrupt_status);
+
+ eth_index = obj->index;
+ SFF_DBG("eth index: %u\n", eth_index);
+ return g_sff_drv->get_eth_interrupt_status(eth_index, buf, PAGE_SIZE);
+}
+
+static ssize_t eth_eeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t count)
+{
+ struct switch_obj *eth_obj;
+ ssize_t rd_len;
+ unsigned int eth_index;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->read_eth_eeprom_data);
+
+ eth_obj = to_switch_obj(kobj);
+ eth_index = eth_obj->index;
+ mem_clear(buf, count);
+ rd_len = g_sff_drv->read_eth_eeprom_data(eth_index, buf, offset, count);
+ if (rd_len < 0) {
+ SFF_ERR("read eth%u eeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
+ eth_index, offset, count, rd_len);
+ return rd_len;
+ }
+
+ SFF_DBG("read eth%u eeprom data success, offset:0x%llx, read len:%lu, really read len:%ld.\n",
+ eth_index, offset, count, rd_len);
+
+ return rd_len;
+}
+
+static ssize_t eth_eeprom_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t offset, size_t count)
+{
+ struct switch_obj *eth_obj;
+ ssize_t wr_len;
+ unsigned int eth_index;
+
+ check_p(g_sff_drv);
+ check_p(g_sff_drv->write_eth_eeprom_data);
+
+ eth_obj = to_switch_obj(kobj);
+ eth_index = eth_obj->index;
+ wr_len = g_sff_drv->write_eth_eeprom_data(eth_index, buf, offset, count);
+ if (wr_len < 0) {
+ SFF_ERR("write eth%u eeprom data error, offset: 0x%llx, read len: %lu, ret: %ld.\n",
+ eth_index, offset, count, wr_len);
+ return wr_len;
+ }
+
+ SFF_DBG("write eth%u eeprom data success, offset:0x%llx, write len:%lu, really write len:%ld.\n",
+ eth_index, offset, count, wr_len);
+
+ return wr_len;
+}
+
+/************************************eth* signal attrs*******************************************/
+static struct switch_attribute eth_power_on_attr = __ATTR(power_on, S_IRUGO | S_IWUSR, eth_power_on_show, eth_power_on_store);
+static struct switch_attribute eth_tx_fault_attr = __ATTR(tx_fault, S_IRUGO, eth_tx_fault_show, NULL);
+static struct switch_attribute eth_tx_disable_attr = __ATTR(tx_disable, S_IRUGO | S_IWUSR, eth_tx_disable_show, eth_tx_disable_store);
+static struct switch_attribute eth_present_attr = __ATTR(present, S_IRUGO, eth_present_show, NULL);
+static struct switch_attribute eth_rx_los_attr = __ATTR(rx_los, S_IRUGO, eth_rx_los_show, NULL);
+static struct switch_attribute eth_reset_attr = __ATTR(reset, S_IRUGO | S_IWUSR, eth_reset_show, eth_reset_store);
+static struct switch_attribute eth_low_power_mode_attr = __ATTR(low_power_mode, S_IRUGO | S_IWUSR, eth_low_power_mode_show, eth_low_power_mode_store);
+static struct switch_attribute eth_interrupt_attr = __ATTR(interrupt, S_IRUGO, eth_interrupt_show, NULL);
+static struct switch_attribute eth_optoe_type_attr = __ATTR(optoe_type, S_IRUGO | S_IWUSR, eth_optoe_type_show, eth_optoe_type_store);
+
+static struct attribute *sff_signal_attrs[] = {
+ ð_power_on_attr.attr,
+ ð_tx_fault_attr.attr,
+ ð_tx_disable_attr.attr,
+ ð_present_attr.attr,
+ ð_rx_los_attr.attr,
+ ð_reset_attr.attr,
+ ð_low_power_mode_attr.attr,
+ ð_interrupt_attr.attr,
+ ð_optoe_type_attr.attr,
+ NULL,
+};
+
+static struct attribute_group sff_signal_attr_group = {
+ .attrs = sff_signal_attrs,
+};
+
+/*******************************transceiver dir and attrs*******************************************/
+static struct switch_attribute transceiver_power_on_attr = __ATTR(power_on, S_IRUGO | S_IWUSR, transceiver_power_on_show, transceiver_power_on_store);
+static struct switch_attribute transceiver_number_attr = __ATTR(number, S_IRUGO, transceiver_number_show, NULL);
+static struct switch_attribute transceiver_present_attr = __ATTR(present, S_IRUGO, transceiver_present_show, NULL);
+
+static struct attribute *transceiver_dir_attrs[] = {
+ &transceiver_power_on_attr.attr,
+ &transceiver_number_attr.attr,
+ &transceiver_present_attr.attr,
+ NULL,
+};
+
+static struct attribute_group sff_transceiver_attr_group = {
+ .attrs = transceiver_dir_attrs,
+};
+
+/* create eth* eeprom attributes */
+static int sff_sub_single_create_eeprom_attrs(unsigned int index)
+{
+ int ret, eeprom_size;
+ struct sff_obj_s *curr_sff;
+
+ check_p(g_sff_drv->get_eth_eeprom_size);
+ eeprom_size = g_sff_drv->get_eth_eeprom_size(index);
+ if (eeprom_size <= 0) {
+ SFF_INFO("eth%u, eeprom_size: %d, don't need to creat eeprom attr.\n",
+ index, eeprom_size);
+ return 0;
+ }
+
+ curr_sff = &g_sff.sff[index - 1];
+ sysfs_bin_attr_init(&curr_sff->bin);
+ curr_sff->bin.attr.name = "eeprom";
+ curr_sff->bin.attr.mode = 0644;
+ curr_sff->bin.read = eth_eeprom_read;
+ curr_sff->bin.write = eth_eeprom_write;
+ curr_sff->bin.size = eeprom_size;
+
+ ret = sysfs_create_bin_file(&curr_sff->sff_obj->kobj, &curr_sff->bin);
+ if (ret) {
+ SFF_ERR("eth%u, create eeprom bin error, ret: %d. \n", index, ret);
+ return -EBADRQC;
+ }
+
+ SFF_DBG("eth%u, create bin file success, eeprom size:%d.\n", index, eeprom_size);
+ curr_sff->sff_creat_bin_flag = 1;
+ return 0;
+}
+
+static int sff_sub_single_create_kobj(struct kobject *parent, unsigned int index)
+{
+ struct sff_obj_s *curr_sff;
+ char sff_dir_name[DIR_NAME_MAX_LEN];
+
+ curr_sff = &g_sff.sff[index - 1];
+ mem_clear(sff_dir_name, sizeof(sff_dir_name));
+ snprintf(sff_dir_name, sizeof(sff_dir_name), "eth%d", index);
+ curr_sff->sff_obj = switch_kobject_create(sff_dir_name, parent);
+ if (!curr_sff->sff_obj) {
+ SFF_ERR("create eth%d object error! \n", index);
+ return -EBADRQC;
+ }
+ curr_sff->sff_obj->index = index;
+ if (sysfs_create_group(&curr_sff->sff_obj->kobj, &sff_signal_attr_group) != 0) {
+ switch_kobject_delete(&curr_sff->sff_obj);
+ return -EBADRQC;
+ }
+
+ SFF_DBG("create eth%d dir and attrs success\n", index);
+ return 0;
+}
+
+/* remove eth directory and attributes */
+static void sff_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct sff_obj_s *curr_sff;
+
+ curr_sff = &g_sff.sff[index - 1];
+ if (curr_sff->sff_obj) {
+ if (curr_sff->sff_creat_bin_flag) {
+ sysfs_remove_bin_file(&curr_sff->sff_obj->kobj, &curr_sff->bin);
+ curr_sff->sff_creat_bin_flag = 0;
+ }
+ sysfs_remove_group(&curr_sff->sff_obj->kobj, &sff_signal_attr_group);
+ switch_kobject_delete(&curr_sff->sff_obj);
+ }
+
+ return;
+}
+
+static int sff_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ int ret;
+
+ ret = sff_sub_single_create_kobj(parent, index);
+ if (ret < 0) {
+ SFF_ERR("create eth%d dir error.\n", index);
+ return ret;
+ }
+
+ sff_sub_single_create_eeprom_attrs(index);
+ return 0;
+}
+
+static int sff_sub_create_kobj_and_attrs(struct kobject *parent, int sff_num)
+{
+ unsigned int sff_index, i;
+
+ g_sff.sff = kzalloc(sizeof(struct sff_obj_s) * sff_num, GFP_KERNEL);
+ if (!g_sff.sff) {
+ SFF_ERR("kzalloc g_sff.sff error, sff number = %d.\n", sff_num);
+ return -ENOMEM;
+ }
+
+ for (sff_index = 1; sff_index <= sff_num; sff_index++) {
+ if (sff_sub_single_create_kobj_and_attrs(parent, sff_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = sff_index; i > 0; i--) {
+ sff_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_sff.sff);
+ g_sff.sff = NULL;
+ return -EBADRQC;
+}
+
+/* create eth directory and attributes */
+static int sff_sub_create(void)
+{
+ int ret;
+
+ ret = sff_sub_create_kobj_and_attrs(&g_sff_obj->kobj, g_sff.sff_number);
+ return ret;
+}
+
+/* delete eth directory and attributes */
+static void sff_sub_remove(void)
+{
+ unsigned int sff_index;
+
+ if (g_sff.sff) {
+ for (sff_index = g_sff.sff_number; sff_index > 0; sff_index--) {
+ sff_sub_single_remove_kobj_and_attrs(sff_index);
+ }
+ kfree(g_sff.sff);
+ g_sff.sff = NULL;
+ }
+ g_sff.sff_number = 0;
+ return;
+}
+
+/* create transceiver directory and attributes */
+static int sff_transceiver_create(void)
+{
+ g_sff_obj = switch_kobject_create("transceiver", NULL);
+ if (!g_sff_obj) {
+ SFF_ERR("switch_kobject_create transceiver error!\n");
+ return -ENOMEM;
+ }
+ g_sff_obj->index = 0;
+ if (sysfs_create_group(&g_sff_obj->kobj, &sff_transceiver_attr_group) != 0) {
+ switch_kobject_delete(&g_sff_obj);
+ SFF_ERR("create transceiver dir attrs error!\n");
+ return -EBADRQC;
+ }
+ return 0;
+}
+
+/* delete transceiver directory and attributes */
+static void sff_transceiver_remove(void)
+{
+ if (g_sff_obj) {
+ sysfs_remove_group(&g_sff_obj->kobj, &sff_transceiver_attr_group);
+ switch_kobject_delete(&g_sff_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_sff_drivers_register(struct s3ip_sysfs_transceiver_drivers_s *drv)
+{
+ int ret, sff_num;
+
+ SFF_INFO("s3ip_sysfs_sff_drivers_register...\n");
+ if (g_sff_drv) {
+ SFF_ERR("g_sff_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_eth_number);
+ g_sff_drv = drv;
+
+ sff_num = g_sff_drv->get_eth_number();
+ if (sff_num <= 0) {
+ SFF_ERR("eth number: %d, don't need to create transceiver dirs and attrs.\n", sff_num);
+ g_sff_drv = NULL;
+ return -EINVAL;
+ }
+
+ mem_clear(&g_sff, sizeof(struct sff_s));
+ g_sff.sff_number = sff_num;
+ ret = sff_transceiver_create();
+ if (ret < 0) {
+ SFF_ERR("create transceiver root dir and attrs failed, ret: %d\n", ret);
+ g_sff_drv = NULL;
+ return ret;
+ }
+ ret = sff_sub_create();
+ if (ret < 0) {
+ SFF_ERR("create transceiver sub dir and attrs failed, ret: %d\n", ret);
+ sff_transceiver_remove();
+ g_sff_drv = NULL;
+ return ret;
+ }
+ SFF_INFO("s3ip_sysfs_sff_drivers_register success\n");
+ return ret;
+}
+
+void s3ip_sysfs_sff_drivers_unregister(void)
+{
+ if (g_sff_drv) {
+ sff_sub_remove();
+ sff_transceiver_remove();
+ g_sff_drv = NULL;
+ SFF_DBG("s3ip_sysfs_sff_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_sff_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_sff_drivers_unregister);
+module_param(g_sff_loglevel, int, 0644);
+MODULE_PARM_DESC(g_sff_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
+module_param(g_sff_present_debug, bool, 0644);
+MODULE_PARM_DESC(g_sff_present_debug, "the sff present debug switch(0: disable, 1:enable, defalut: 0).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/vol_sensor_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/vol_sensor_sysfs.c
new file mode 100644
index 000000000000..737aa3d94393
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/vol_sensor_sysfs.c
@@ -0,0 +1,416 @@
+/*
+ * An vol_sensor_sysfs driver for voltage sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "vol_sensor_sysfs.h"
+
+static int g_vol_sensor_loglevel = 0;
+
+#define VOL_SENSOR_INFO(fmt, args...) do { \
+ if (g_vol_sensor_loglevel & INFO) { \
+ printk(KERN_INFO "[VOL_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define VOL_SENSOR_ERR(fmt, args...) do { \
+ if (g_vol_sensor_loglevel & ERR) { \
+ printk(KERN_ERR "[VOL_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define VOL_SENSOR_DBG(fmt, args...) do { \
+ if (g_vol_sensor_loglevel & DBG) { \
+ printk(KERN_DEBUG "[VOL_SENSOR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+struct vol_sensor_obj_s {
+ struct switch_obj *obj;
+};
+
+struct vol_sensor_s {
+ unsigned int vol_number;
+ struct vol_sensor_obj_s *vol;
+};
+
+static struct s3ip_sysfs_vol_sensor_drivers_s *g_vol_sensor_drv = NULL;
+static struct vol_sensor_s g_vol_sensor;
+static struct switch_obj *g_vol_sensor_obj = NULL;
+
+static ssize_t vol_sensor_number_show(struct switch_obj *obj, struct switch_attribute *attr,
+ char *buf)
+{
+ return (ssize_t)snprintf(buf, PAGE_SIZE, "%u\n", g_vol_sensor.vol_number);
+}
+
+static ssize_t vol_sensor_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_value);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_value(vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t vol_sensor_alias_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_alias);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_alias(vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t vol_sensor_type_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_type);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_type(vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t vol_sensor_max_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_max);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_max(vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t vol_sensor_max_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int vol_index;
+ int ret;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->set_main_board_vol_max);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ ret = g_vol_sensor_drv->set_main_board_vol_max(vol_index, buf, count);
+ if (ret < 0) {
+ VOL_SENSOR_ERR("set vol%u max threshold failed, value: %s, count: %lu, ret: %d\n",
+ vol_index, buf, count, ret);
+ return ret;
+ }
+ VOL_SENSOR_DBG("set vol%u max threshold success, value: %s, count: %lu, ret: %d\n",
+ vol_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t vol_sensor_min_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_min);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_min(vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t vol_sensor_min_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ unsigned int vol_index;
+ int ret;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->set_main_board_vol_min);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ ret = g_vol_sensor_drv->set_main_board_vol_min(vol_index, buf, count);
+ if (ret < 0) {
+ VOL_SENSOR_ERR("set vol%u min threshold failed, value: %s, count: %lu, ret: %d\n",
+ vol_index, buf, count, ret);
+ return ret;
+ }
+ VOL_SENSOR_DBG("set vol%u min threshold success, value: %s, count: %lu, ret: %d\n",
+ vol_index, buf, count, ret);
+ return count;
+}
+
+static ssize_t vol_sensor_range_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_range);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_range(vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t vol_sensor_nominal_value_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_nominal_value);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_nominal_value(vol_index, buf, PAGE_SIZE);
+}
+
+static ssize_t vol_sensor_monitor_flag_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ unsigned int vol_index;
+
+ check_p(g_vol_sensor_drv);
+ check_p(g_vol_sensor_drv->get_main_board_vol_monitor_flag);
+
+ vol_index = obj->index;
+ VOL_SENSOR_DBG("vol index: %u\n", vol_index);
+ return g_vol_sensor_drv->get_main_board_vol_monitor_flag(vol_index, buf, PAGE_SIZE);
+}
+
+/************************************vol_sensor dir and attrs*******************************************/
+static struct switch_attribute num_vol_att = __ATTR(number, S_IRUGO, vol_sensor_number_show, NULL);
+
+static struct attribute *vol_sensor_dir_attrs[] = {
+ &num_vol_att.attr,
+ NULL,
+};
+
+static struct attribute_group vol_sensor_root_attr_group = {
+ .attrs = vol_sensor_dir_attrs,
+};
+
+/*******************************vol1 vol2 dir and attrs*******************************************/
+static struct switch_attribute vol_value_attr = __ATTR(value, S_IRUGO, vol_sensor_value_show, NULL);
+static struct switch_attribute vol_alias_attr = __ATTR(alias, S_IRUGO, vol_sensor_alias_show, NULL);
+static struct switch_attribute vol_type_attr = __ATTR(type, S_IRUGO, vol_sensor_type_show, NULL);
+static struct switch_attribute vol_max_attr = __ATTR(max, S_IRUGO | S_IWUSR, vol_sensor_max_show, vol_sensor_max_store);
+static struct switch_attribute vol_min_attr = __ATTR(min, S_IRUGO | S_IWUSR, vol_sensor_min_show, vol_sensor_min_store);
+static struct switch_attribute vol_range_attr = __ATTR(range, S_IRUGO, vol_sensor_range_show, NULL);
+static struct switch_attribute vol_nominal_value_attr = __ATTR(nominal_value, S_IRUGO, vol_sensor_nominal_value_show, NULL);
+static struct switch_attribute vol_monitor_flag_attr = __ATTR(monitor_flag, S_IRUGO, vol_sensor_monitor_flag_show, NULL);
+
+static struct attribute *vol_sensor_attrs[] = {
+ &vol_value_attr.attr,
+ &vol_alias_attr.attr,
+ &vol_type_attr.attr,
+ &vol_max_attr.attr,
+ &vol_min_attr.attr,
+ &vol_range_attr.attr,
+ &vol_nominal_value_attr.attr,
+ &vol_monitor_flag_attr.attr,
+ NULL,
+};
+
+static struct attribute_group vol_sensor_attr_group = {
+ .attrs = vol_sensor_attrs,
+};
+
+static int vol_sensor_sub_single_create_kobj_and_attrs(struct kobject *parent, unsigned int index)
+{
+ char name[DIR_NAME_MAX_LEN];
+ struct vol_sensor_obj_s *vol_sensor;
+
+ vol_sensor = &g_vol_sensor.vol[index - 1];
+ mem_clear(name, sizeof(name));
+ snprintf(name, sizeof(name), "vol%u", index);
+ vol_sensor->obj = switch_kobject_create(name, parent);
+ if (!vol_sensor->obj) {
+ VOL_SENSOR_ERR("create %s object error.\n", name);
+ return -ENOMEM;
+ }
+
+ vol_sensor->obj->index = index;
+ if (sysfs_create_group(&vol_sensor->obj->kobj, &vol_sensor_attr_group) != 0) {
+ VOL_SENSOR_ERR("create %s attrs error.\n", name);
+ switch_kobject_delete(&vol_sensor->obj);
+ return -EBADRQC;
+ }
+ VOL_SENSOR_DBG("create %s dir and attrs success.\n", name);
+
+ return 0;
+}
+
+static void vol_sensor_sub_single_remove_kobj_and_attrs(unsigned int index)
+{
+ struct vol_sensor_obj_s *vol_sensor;
+
+ vol_sensor = &g_vol_sensor.vol[index - 1];
+ if (vol_sensor->obj) {
+ sysfs_remove_group(&vol_sensor->obj->kobj, &vol_sensor_attr_group);
+ switch_kobject_delete(&vol_sensor->obj);
+ VOL_SENSOR_DBG("delete vol%u dir and attrs success.\n", index);
+ }
+
+ return;
+}
+
+static int vol_sensor_sub_create_kobj_and_attrs(struct kobject *parent, int vol_num)
+{
+ unsigned int vol_index, i;
+
+ g_vol_sensor.vol = kzalloc(sizeof(struct vol_sensor_obj_s) * vol_num, GFP_KERNEL);
+ if (!g_vol_sensor.vol) {
+ VOL_SENSOR_ERR("kzalloc g_vol_sensor.vol error, vol number: %d.\n", vol_num);
+ return -ENOMEM;
+ }
+
+ for (vol_index = 1; vol_index <= vol_num; vol_index++) {
+ if (vol_sensor_sub_single_create_kobj_and_attrs(parent, vol_index) != 0) {
+ goto error;
+ }
+ }
+ return 0;
+error:
+ for (i = vol_index; i > 0; i--) {
+ vol_sensor_sub_single_remove_kobj_and_attrs(i);
+ }
+ kfree(g_vol_sensor.vol);
+ g_vol_sensor.vol = NULL;
+ return -EBADRQC;
+}
+
+/* create vol[1-n] directory and attributes*/
+static int vol_sensor_sub_create(void)
+{
+ int ret;
+
+ ret = vol_sensor_sub_create_kobj_and_attrs(&g_vol_sensor_obj->kobj, g_vol_sensor.vol_number);
+ return ret;
+}
+
+/* delete vol[1-n] directory and attributes*/
+static void vol_sensor_sub_remove(void)
+{
+ unsigned int vol_index;
+
+ if (g_vol_sensor.vol) {
+ for (vol_index = g_vol_sensor.vol_number; vol_index > 0; vol_index--) {
+ vol_sensor_sub_single_remove_kobj_and_attrs(vol_index);
+ }
+ kfree(g_vol_sensor.vol);
+ g_vol_sensor.vol = NULL;
+ }
+
+ return;
+}
+
+/* create vol_sensor directory and number attributes */
+static int vol_sensor_root_create(void)
+{
+ g_vol_sensor_obj = switch_kobject_create("vol_sensor", NULL);
+ if (!g_vol_sensor_obj) {
+ VOL_SENSOR_ERR("switch_kobject_create vol_sensor error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_vol_sensor_obj->kobj, &vol_sensor_root_attr_group) != 0) {
+ switch_kobject_delete(&g_vol_sensor_obj);
+ VOL_SENSOR_ERR("create vol_sensor dir attrs error!\n");
+ return -EBADRQC;
+ }
+
+ return 0;
+}
+
+/* delete vol_sensor directory and number attributes */
+static void vol_sensor_root_remove(void)
+{
+ if (g_vol_sensor_obj) {
+ sysfs_remove_group(&g_vol_sensor_obj->kobj, &vol_sensor_root_attr_group);
+ switch_kobject_delete(&g_vol_sensor_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_vol_sensor_drivers_register(struct s3ip_sysfs_vol_sensor_drivers_s *drv)
+{
+ int ret, vol_num;
+
+ VOL_SENSOR_INFO("s3ip_sysfs_vol_sensor_drivers_register...\n");
+ if (g_vol_sensor_drv) {
+ VOL_SENSOR_ERR("g_vol_sensor_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ check_p(drv->get_main_board_vol_number);
+ g_vol_sensor_drv = drv;
+
+ vol_num = g_vol_sensor_drv->get_main_board_vol_number();
+ if (vol_num <= 0) {
+ VOL_SENSOR_ERR("vol sensor number: %d, don't need to create vol_sensor dirs and attrs.\n",
+ vol_num);
+ g_vol_sensor_drv = NULL;
+ return -EINVAL;
+ }
+ mem_clear(&g_vol_sensor, sizeof(struct vol_sensor_s));
+ g_vol_sensor.vol_number = vol_num;
+ ret = vol_sensor_root_create();
+ if (ret < 0) {
+ VOL_SENSOR_ERR("create vol_sensor root dir and attrs failed, ret: %d\n", ret);
+ g_vol_sensor_drv = NULL;
+ return ret;
+ }
+
+ ret = vol_sensor_sub_create();
+ if (ret < 0) {
+ VOL_SENSOR_ERR("create vol_sensor sub dir and attrs failed, ret: %d\n", ret);
+ vol_sensor_root_remove();
+ g_vol_sensor_drv = NULL;
+ return ret;
+ }
+ VOL_SENSOR_INFO("s3ip_sysfs_vol_sensor_drivers_register success\n");
+ return ret;
+}
+
+void s3ip_sysfs_vol_sensor_drivers_unregister(void)
+{
+ if (g_vol_sensor_drv) {
+ vol_sensor_sub_remove();
+ vol_sensor_root_remove();
+ g_vol_sensor_drv = NULL;
+ VOL_SENSOR_DBG("s3ip_sysfs_vol_sensor_drivers_unregister success.\n");
+ }
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_vol_sensor_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_vol_sensor_drivers_unregister);
+module_param(g_vol_sensor_loglevel, int, 0644);
+MODULE_PARM_DESC(g_vol_sensor_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/watchdog_sysfs.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/watchdog_sysfs.c
new file mode 100644
index 000000000000..3188f18958f4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/s3ip_sysfs/sysfs_driver/watchdog_sysfs.c
@@ -0,0 +1,241 @@
+/*
+ * An watchdog_sysfs driver for watchdog sysfs devcie function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+
+#include "switch.h"
+#include "watchdog_sysfs.h"
+
+static int g_wdt_loglevel = 0;
+
+#define WDT_INFO(fmt, args...) do { \
+ if (g_wdt_loglevel & INFO) { \
+ printk(KERN_INFO "[WDT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define WDT_ERR(fmt, args...) do { \
+ if (g_wdt_loglevel & ERR) { \
+ printk(KERN_ERR "[WDT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define WDT_DBG(fmt, args...) do { \
+ if (g_wdt_loglevel & DBG) { \
+ printk(KERN_DEBUG "[WDT_SYSFS][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+typedef enum wdt_enable_status_e {
+ WDT_DISENABLE = 0, /* close watchdog */
+ WDT_ENABLE = 1, /* open watchdog */
+} wdt_enable_status_t;
+
+static struct switch_obj *g_watchdog_obj = NULL;
+static struct s3ip_sysfs_watchdog_drivers_s *g_wdt_drv = NULL;
+
+static ssize_t watchdog_identify_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_wdt_drv);
+ check_p(g_wdt_drv->get_watchdog_identify);
+
+ return g_wdt_drv->get_watchdog_identify(buf, PAGE_SIZE);
+}
+
+static ssize_t watchdog_timeleft_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_wdt_drv);
+ check_p(g_wdt_drv->get_watchdog_timeleft);
+
+ return g_wdt_drv->get_watchdog_timeleft(buf, PAGE_SIZE);
+}
+
+static ssize_t watchdog_timeout_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_wdt_drv);
+ check_p(g_wdt_drv->get_watchdog_timeout);
+
+ return g_wdt_drv->get_watchdog_timeout(buf, PAGE_SIZE);
+}
+
+static ssize_t watchdog_timeout_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_wdt_drv);
+ check_p(g_wdt_drv->set_watchdog_timeout);
+
+ sscanf(buf, "%d", &value);
+ if (value < 0) {
+ WDT_ERR("invaild timeout value: %d, can't set watchdog timeout\n", value);
+ return -EINVAL;
+ }
+
+ ret = g_wdt_drv->set_watchdog_timeout(value);
+ if (ret < 0) {
+ WDT_ERR("set watchdog timeout value: %d failed, ret: %d\n", value, ret);
+ return ret;
+ }
+ WDT_DBG("set watchdog timeout value: %d success\n", ret);
+ return count;
+}
+
+static ssize_t watchdog_enable_status_show(struct switch_obj *obj, struct switch_attribute *attr, char *buf)
+{
+ check_p(g_wdt_drv);
+ check_p(g_wdt_drv->get_watchdog_enable_status);
+
+ return g_wdt_drv->get_watchdog_enable_status(buf, PAGE_SIZE);
+}
+
+static ssize_t watchdog_enable_status_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_wdt_drv);
+ check_p(g_wdt_drv->set_watchdog_enable_status);
+
+ sscanf(buf, "%d", &value);
+ if ((value != WDT_DISENABLE) && (value != WDT_ENABLE)) {
+ WDT_ERR("invaild enable value: %d, can't set watchdog enable status\n", value);
+ return -EINVAL;
+ }
+
+ ret = g_wdt_drv->set_watchdog_enable_status(value);
+ if (ret < 0) {
+ WDT_ERR("set watchdog enable status %d failed, ret: %d\n", value, ret);
+ return ret;
+ }
+ WDT_DBG("set watchdog enable status %d success\n", ret);
+ return count;
+}
+
+static ssize_t watchdog_reset_store(struct switch_obj *obj, struct switch_attribute *attr,
+ const char* buf, size_t count)
+{
+ int ret, value;
+
+ check_p(g_wdt_drv);
+ check_p(g_wdt_drv->set_watchdog_reset);
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret) {
+ WDT_ERR("invalid value: %s \n", buf);
+ return -EINVAL;
+ }
+
+ ret = g_wdt_drv->set_watchdog_reset(value);
+ if (ret < 0) {
+ WDT_ERR("set watchdog reset %d failed, ret: %d\n", value, ret);
+ return ret;
+ }
+ WDT_DBG("set watchdog reset %d success\n", ret);
+ return count;
+}
+
+/************************************watchdog*******************************************/
+static struct switch_attribute watchdog_identify_attr = __ATTR(identify, S_IRUGO, watchdog_identify_show, NULL);
+static struct switch_attribute watchdog_timeleft_attr = __ATTR(timeleft, S_IRUGO, watchdog_timeleft_show, NULL);
+static struct switch_attribute watchdog_timeout_attr = __ATTR(timeout, S_IRUGO | S_IWUSR, watchdog_timeout_show, watchdog_timeout_store);
+static struct switch_attribute watchdog_enable_attr = __ATTR(enable, S_IRUGO | S_IWUSR, watchdog_enable_status_show, watchdog_enable_status_store);
+static struct switch_attribute watchdog_reset_attr = __ATTR(reset, S_IWUSR, NULL, watchdog_reset_store);
+
+static struct attribute *watchdog_dir_attrs[] = {
+ &watchdog_identify_attr.attr,
+ &watchdog_timeleft_attr.attr,
+ &watchdog_timeout_attr.attr,
+ &watchdog_enable_attr.attr,
+ &watchdog_reset_attr.attr,
+ NULL,
+};
+
+static struct attribute_group watchdog_attr_group = {
+ .attrs = watchdog_dir_attrs,
+};
+
+/* create watchdog directory and attributes */
+static int watchdog_root_create(void)
+{
+ g_watchdog_obj = switch_kobject_create("watchdog", NULL);
+ if (!g_watchdog_obj) {
+ WDT_ERR("switch_kobject_create watchdog error!\n");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(&g_watchdog_obj->kobj, &watchdog_attr_group) != 0) {
+ switch_kobject_delete(&g_watchdog_obj);
+ WDT_ERR("create fan dir attrs error!\n");
+ return -EBADRQC;
+ }
+
+ return 0;
+}
+
+/* delete watchdog directory and attributes */
+static void watchdog_root_remove(void)
+{
+ if (g_watchdog_obj) {
+ sysfs_remove_group(&g_watchdog_obj->kobj, &watchdog_attr_group);
+ switch_kobject_delete(&g_watchdog_obj);
+ }
+
+ return;
+}
+
+int s3ip_sysfs_watchdog_drivers_register(struct s3ip_sysfs_watchdog_drivers_s *drv)
+{
+ int ret;
+
+ WDT_INFO("s3ip_sysfs_watchdog_drivers_register...\n");
+ if (g_wdt_drv) {
+ WDT_ERR("g_wdt_drv is not NULL, can't register\n");
+ return -EPERM;
+ }
+
+ check_p(drv);
+ g_wdt_drv = drv;
+
+ ret = watchdog_root_create();
+ if (ret < 0) {
+ WDT_ERR("watchdog create error.\n");
+ g_wdt_drv = NULL;
+ return ret;
+ }
+ WDT_INFO("s3ip_sysfs_watchdog_drivers_register success\n");
+ return 0;
+}
+
+void s3ip_sysfs_watchdog_drivers_unregister(void)
+{
+ if (g_wdt_drv) {
+ watchdog_root_remove();
+ g_wdt_drv = NULL;
+ WDT_DBG("s3ip_sysfs_watchdog_drivers_unregister success.\n");
+ }
+
+ return;
+}
+
+EXPORT_SYMBOL(s3ip_sysfs_watchdog_drivers_register);
+EXPORT_SYMBOL(s3ip_sysfs_watchdog_drivers_unregister);
+module_param(g_wdt_loglevel, int, 0644);
+MODULE_PARM_DESC(g_wdt_loglevel, "the log level(info=0x1, err=0x2, dbg=0x4).\n");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_csu550.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_csu550.c
index 0b95663b9bad..55f6a529c7be 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_csu550.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_csu550.c
@@ -1,8 +1,21 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Hardware monitoring driver for PMBus devices
+ * An wb_csu550 driver for psu csu550 function
*
- * Copyright (c) 2010, 2011 Ericsson AB.
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_i2c_bus_drv.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_i2c_bus_drv.c
index 22cd9e16de08..b237df4e36a9 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_i2c_bus_drv.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_i2c_bus_drv.c
@@ -1,7 +1,23 @@
/*
- * fpga_i2c_bus_drv.c
- * ko to create fpga i2c adapter
+ * An wb_fpga_i2c_bus_drv driver for create fpga i2c adapter function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include
#include
#include
@@ -34,6 +50,8 @@ extern int io_device_func_write(const char *path, uint32_t pos, uint8_t *val, si
extern int io_device_func_read(const char *path, uint32_t pos, uint8_t *val, size_t size);
extern int spi_device_func_read(const char *path, uint32_t offset, uint8_t *buf, size_t count);
extern int spi_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count);
+extern int indirect_device_func_write(const char *path, uint32_t pos, uint8_t *val, size_t size);
+extern int indirect_device_func_read(const char *path, uint32_t pos, uint8_t *val, size_t size);
#define FPGA_I2C_STRETCH_TIMEOUT (0x01)
#define FPGA_I2C_DEADLOCK_FAILED (0x02)
@@ -53,6 +71,7 @@ extern int spi_device_func_write(const char *path, uint32_t offset, uint8_t *buf
#define SYMBOL_PCIE_DEV_MODE (3)
#define SYMBOL_IO_DEV_MODE (4)
#define SYMBOL_SPI_DEV_MODE (5)
+#define SYMBOL_INDIRECT_DEV_MODE (6)
int g_wb_fpga_i2c_debug = 0;
int g_wb_fpga_i2c_error = 0;
@@ -170,6 +189,9 @@ static int fpga_device_write(fpga_i2c_dev_t *fpga_i2c, uint32_t pos, uint8_t *va
case SYMBOL_SPI_DEV_MODE:
ret = spi_device_func_write(fpga_i2c->dev_name, pos, val, size);
break;
+ case SYMBOL_INDIRECT_DEV_MODE:
+ ret = indirect_device_func_write(fpga_i2c->dev_name, pos, val, size);
+ break;
default:
FPGA_I2C_ERROR("err func_mode %d, write failed.\n", fpga_i2c->i2c_func_mode);
return -EINVAL;
@@ -198,6 +220,9 @@ static int fpga_device_read(fpga_i2c_dev_t *fpga_i2c, uint32_t pos, uint8_t *val
case SYMBOL_SPI_DEV_MODE:
ret = spi_device_func_read(fpga_i2c->dev_name, pos, val, size);
break;
+ case SYMBOL_INDIRECT_DEV_MODE:
+ ret = indirect_device_func_read(fpga_i2c->dev_name, pos, val, size);
+ break;
default:
FPGA_I2C_ERROR("err func_mode %d, read failed.\n", fpga_i2c->i2c_func_mode);
return -EINVAL;
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pca954x_drv.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pca954x_drv.c
index 25f2d60b9334..d55d0cef122f 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pca954x_drv.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pca954x_drv.c
@@ -1,3 +1,23 @@
+/*
+ * An wb_fpga_pca954x_drv driver for create fpga pca954x adapter function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
@@ -17,6 +37,7 @@ extern int i2c_device_func_write(const char *path, uint32_t pos, uint8_t *val, s
extern int pcie_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count);
extern int io_device_func_write(const char *path, uint32_t pos, uint8_t *val, size_t size);
extern int spi_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count);
+extern int indirect_device_func_write(const char *path, uint32_t pos, uint8_t *val, size_t size);
#define PCA954X_MAX_NCHANS (8)
#define FPGA_INTERNAL_PCA9548 (1)
@@ -29,6 +50,7 @@ extern int spi_device_func_write(const char *path, uint32_t offset, uint8_t *buf
#define SYMBOL_PCIE_DEV_MODE (3)
#define SYMBOL_IO_DEV_MODE (4)
#define SYMBOL_SPI_DEV_MODE (5)
+#define SYMBOL_INDIRECT_DEV_MODE (6)
int g_fpga_pca954x_debug = 0;
int g_fpga_pca954x_error = 0;
@@ -189,6 +211,9 @@ static int fpga_device_write(fpga_i2c_dev_t *fpga_i2c, int pos, unsigned char *v
case SYMBOL_SPI_DEV_MODE:
ret = spi_device_func_write(fpga_i2c->dev_name, pos, val, size);
break;
+ case SYMBOL_INDIRECT_DEV_MODE:
+ ret = indirect_device_func_write(fpga_i2c->dev_name, pos, val, size);
+ break;
default:
FPGA_PCA954X_ERROR("err func_mode %d, write failed.\n", fpga_i2c->i2c_func_mode);
return -EINVAL;
@@ -416,7 +441,6 @@ static int fpga_i2c_pca954x_probe(struct i2c_client *client, const struct i2c_de
data->type = id->driver_data;
/* BUS ID */
ret = of_property_read_u32(dev->of_node, "fpga_9548_flag", &data->fpga_9548_flag);
- ret += of_property_read_u32(dev->of_node, "fpga_9548_reset_flag", &data->fpga_9548_reset_flag);
if (ret != 0) {
dev_err(&client->dev, "Failed to get 954x dts config, ret:%d.\n", ret);
ret = -EINVAL;
@@ -431,7 +455,8 @@ static int fpga_i2c_pca954x_probe(struct i2c_client *client, const struct i2c_de
FPGA_PCA954X_VERBOSE("pca9548_base_nr:%u.\n", data->pca9548_base_nr);
}
}
-
+ data->fpga_9548_reset_flag = 1;
+ dev_info(&client->dev, "pca9548_reset_mode is forcibly set to the hardware automatic reset mode.\n");
if (data->fpga_9548_flag != FPGA_EXTERNAL_PCA9548 && data->fpga_9548_flag != FPGA_INTERNAL_PCA9548) {
dev_err(&client->dev, "Error: fpga 954x flag config error, value:0x%x.\n", data->fpga_9548_flag);
ret = -EINVAL;
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pcie.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pcie.c
index baabfb5cd4d0..43fc67419f0a 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pcie.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_fpga_pcie.c
@@ -1,7 +1,23 @@
/*
- * wb_fpga_pcie.c
- * ko to enable fpga pcie
+ * An wb_fpga_pcie driver for create fpga pcie adapter function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_d1500.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_d1500.c
index 7d5d5da87ea7..25fa7acc1f1f 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_d1500.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_d1500.c
@@ -1,10 +1,24 @@
/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
+ * An wb_gpio_d1500 driver for gpio d1500 function
*
- * Copyright (C) 2011, 2012 Cavium Inc.
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_device.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_device.c
index 75f883b5909d..cd1fc43da118 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_device.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_gpio_device.c
@@ -1,3 +1,23 @@
+/*
+ * An wb_gpio_device driver for gpio device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.c
index 59cee0b1e1c0..69b2aad0e7c8 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.c
@@ -1,7 +1,23 @@
/*
- * wb_io_dev.c
- * ko to read/write i2c client through /dev/XXX device
+ * An wb_i2c_dev driver for i2c dev function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include
#include
#include
@@ -27,8 +43,8 @@
#define WIDTH_2Byte (2)
#define WIDTH_4Byte (4)
-#define KERNEL_SPASE (0)
-#define USER_SPASE (1)
+#define KERNEL_SPACE (0)
+#define USER_SPACE (1)
static int g_i2c_dev_debug = 0;
static int g_i2c_dev_error = 0;
@@ -467,7 +483,7 @@ static ssize_t i2c_dev_read(struct file *file, char __user *buf, size_t count, l
}
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
I2C_DEV_DEBUG_DMESG("user space read, buf: %p, offset: %lld, read count %lu.\n",
buf, *offset, count);
if (copy_to_user(buf, val, read_len)) {
@@ -491,7 +507,7 @@ static ssize_t i2c_dev_read_user(struct file *file, char __user *buf, size_t cou
I2C_DEV_DEBUG_DMESG("i2c_dev_read_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = i2c_dev_read(file, buf, count, offset, USER_SPASE);
+ ret = i2c_dev_read(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -501,7 +517,7 @@ static ssize_t i2c_dev_read_iter(struct kiocb *iocb, struct iov_iter *to)
I2C_DEV_DEBUG_DMESG("i2c_dev_read_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, to->count, iocb->ki_pos);
- ret = i2c_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = i2c_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
@@ -530,7 +546,7 @@ static ssize_t i2c_dev_write(struct file *file, const char __user *buf, size_t c
mem_clear(val, sizeof(val));
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
I2C_DEV_DEBUG_DMESG("user space write, buf: %p, offset: %lld, write count %lu.\n",
buf, *offset, count);
if (copy_from_user(val, buf, count)) {
@@ -560,7 +576,7 @@ static ssize_t i2c_dev_write_user(struct file *file, const char __user *buf, siz
I2C_DEV_DEBUG_DMESG("i2c_dev_write_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = i2c_dev_write(file, buf, count, offset, USER_SPASE);
+ ret = i2c_dev_write(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -570,7 +586,7 @@ static ssize_t i2c_dev_write_iter(struct kiocb *iocb, struct iov_iter *from)
I2C_DEV_DEBUG_DMESG("i2c_dev_write_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, from->count, iocb->ki_pos);
- ret = i2c_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = i2c_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.h
index 9cc95d88e804..5d294a7ed410 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_dev.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_i2c_dev driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_I2C_DEV_H__
#define __WB_I2C_DEV_H__
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_gpio_device.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_gpio_device.c
index 80f18b2eab55..f884dd202e6a 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_gpio_device.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_gpio_device.c
@@ -1,3 +1,23 @@
+/*
+ * An wb_i2c_gpio_device driver for i2c gpio device adapter function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.c
index 854675d9fa99..5c7c566ed4fe 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.c
@@ -1,21 +1,7 @@
/*
- * I2C multiplexer
+ * An wb_i2c_mux_pca954x driver for i2c pca954x multiplexer/switch function
*
- * 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.
+ * Copyright (C) 2024 Micas Networks Inc.
*
* Based on:
* pca954x.c from Kumar Gala
@@ -30,11 +16,22 @@
* 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.
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.h
index beed9b2f94ac..700b36e0236f 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca954x.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_i2c_mux_pca954x driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_I2C_MUX_PCA954X_H__
#define __WB_I2C_MUX_PCA954X_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.c
index a3ae9f4b2431..83b0774ec901 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.c
@@ -1,19 +1,21 @@
/*
- * I2C multiplexer driver for PCA9541 bus master selector
+ * An wb_i2c_mux_pca9641 driver for pca9641 multiplexer/switch function
*
- * Copyright (c) 2010 Ericsson AB.
+ * Copyright (C) 2024 Micas Networks Inc.
*
- * Author: Guenter Roeck
+ * 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.
*
- * Derived from:
- * pca954x.c
+ * 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.
*
- * 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.
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.h
index b87f7585567b..8c8ffa3da03d 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_mux_pca9641.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_i2c_mux_pca9641 driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_I2C_MUX_PCA9641_H__
#define __WB_I2C_MUX_PCA9641_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.c
index 20f8954cce83..643fc3b605d7 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.c
@@ -1,12 +1,21 @@
-// SPDX-License-Identifier: GPL-2.0
/*
- * i2c-ocores.c: I2C bus driver for OpenCores I2C controller
- * (https://opencores.org/project/i2c/overview)
+ * An wb_i2c_ocores driver for i2c ocores function
*
- * Peter Korsgaard
+ * Copyright (C) 2024 Micas Networks Inc.
*
- * Support for the GRLIB port of the controller by
- * Andreas Larsson
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.h
index d413ebb3ad44..8b2cd206c084 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_i2c_ocores.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_ocores driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_I2C_OCORES_H__
#define __WB_I2C_OCORES_H__
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_indirect_dev.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_indirect_dev.c
new file mode 100644
index 000000000000..c0a730e77462
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_indirect_dev.c
@@ -0,0 +1,869 @@
+/*
+ * An wb_indirect_dev driver for indirect adapter device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "wb_indirect_dev.h"
+#define MODULE_NAME "wb-indirect-dev"
+
+#define SYMBOL_I2C_DEV_MODE (1)
+#define FILE_MODE (2)
+#define SYMBOL_PCIE_DEV_MODE (3)
+#define SYMBOL_IO_DEV_MODE (4)
+#define SYMBOL_SPI_DEV_MODE (5)
+
+#define KERNEL_SPACE (0)
+#define USER_SPACE (1)
+
+#define MAX_INDIRECT_DEV_NUM (256)
+#define INDIRECT_ADDR_H(addr) ((addr >> 8) & 0xff)
+#define INDIRECT_ADDR_L(addr) ((addr) & 0xff)
+#define INDIRECT_OP_WRITE (0x2)
+#define INDIRECT_OP_READ (0x3)
+
+static int g_indirect_dev_debug = 0;
+static int g_indirect_dev_error = 0;
+
+module_param(g_indirect_dev_debug, int, S_IRUGO | S_IWUSR);
+module_param(g_indirect_dev_error, int, S_IRUGO | S_IWUSR);
+
+#define INDIRECT_DEV_INFO(fmt, args...) do { \
+ printk(KERN_INFO "[INDIRECT_DEV][INFO][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+} while (0)
+
+#define INDIRECT_DEV_DEBUG(fmt, args...) do { \
+ if (g_indirect_dev_debug) { \
+ printk(KERN_DEBUG "[INDIRECT_DEV][DEBUG][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+#define INDIRECT_DEV_ERROR(fmt, args...) do { \
+ if (g_indirect_dev_error) { \
+ printk(KERN_ERR "[INDIRECT_DEV][ERR][func:%s line:%d]\n"fmt, __func__, __LINE__, ## args); \
+ } \
+} while (0)
+
+static struct indirect_dev_info* indirect_dev_arry[MAX_INDIRECT_DEV_NUM];
+
+static int noop_pre(struct kprobe *p, struct pt_regs *regs) { return 0; }
+static struct kprobe kp = {
+ .symbol_name = "kallsyms_lookup_name",
+};
+unsigned long (*kallsyms_lookup_name_fun)(const char *name) = NULL;
+
+/* Call kprobe to find the address location of kallsyms_lookup_name */
+static int find_kallsyms_lookup_name(void)
+{
+ int ret = -1;
+
+ kp.pre_handler = noop_pre;
+ ret = register_kprobe(&kp);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("register_kprobe failed, error:%d\n", ret);
+ return ret;
+ }
+ INDIRECT_DEV_DEBUG("kallsyms_lookup_name addr: %p\n", kp.addr);
+ kallsyms_lookup_name_fun = (void*)kp.addr;
+ unregister_kprobe(&kp);
+
+ return ret;
+}
+
+struct indirect_dev_info {
+ const char *name; /* generate dev name */
+ const char *logic_dev_name; /* dependent dev name */
+ uint32_t indirect_len; /* dev data len */
+ uint32_t data_bus_width; /* dev data_bus_width */
+ uint32_t addr_bus_width; /* dev addr_bus_width */
+ uint32_t wr_data; /* dependent dev wr date reg */
+ uint32_t wr_data_width; /* dependent dev wr_data_width */
+ uint32_t addr_low; /* dependent dev w/r addr reg low */
+ uint32_t addr_high; /* dependent dev w/r addr reg high */
+ uint32_t rd_data; /* dependent dev rd date reg */
+ uint32_t rd_data_width; /* dependent dev rd_data_width */
+ uint32_t opt_ctl; /* dependent dev opt code reg */
+ uint32_t logic_func_mode; /* 1: i2c, 2: file, 3:pcie, 4:io, 5:spi */
+ unsigned long write_intf_addr;
+ unsigned long read_intf_addr;
+ spinlock_t indirect_dev_lock;
+ struct miscdevice misc;
+ struct device *dev;
+};
+
+static int wb_dev_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)) {
+ INDIRECT_DEV_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) {
+ INDIRECT_DEV_ERROR("vfs_iter_read failed, path=%s, addr=0x%x, size=%zu, 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 wb_dev_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)) {
+ INDIRECT_DEV_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) {
+ INDIRECT_DEV_ERROR("vfs_iter_write failed, path=%s, addr=0x%x, size=%zu, 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 wb_logic_reg_write(struct indirect_dev_info *indirect_dev, uint32_t pos, uint8_t *val, size_t size)
+{
+ device_func_write pfunc;
+
+ pfunc = (device_func_write)indirect_dev->write_intf_addr;
+ return pfunc(indirect_dev->logic_dev_name, pos, val, size);
+}
+
+static int wb_logic_reg_read(struct indirect_dev_info *indirect_dev, uint32_t pos, uint8_t *val, size_t size)
+{
+ device_func_read pfunc;
+
+ pfunc = (device_func_read)indirect_dev->read_intf_addr;
+ return pfunc(indirect_dev->logic_dev_name, pos, val, size);
+}
+
+
+static int indirect_addressing_read(struct indirect_dev_info *indirect_dev, uint8_t *buf, uint32_t address, uint32_t rd_data_width)
+{
+ uint8_t addr_l, addr_h, op_code;
+ unsigned long flags;
+ int ret = 0;
+
+ addr_h = INDIRECT_ADDR_H(address);
+ addr_l = INDIRECT_ADDR_L(address);
+ op_code = INDIRECT_OP_READ;
+
+ spin_lock_irqsave(&indirect_dev->indirect_dev_lock, flags);
+
+ ret = wb_logic_reg_write(indirect_dev, indirect_dev->addr_low, &addr_l, WIDTH_1Byte);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_read write reg error.offset = 0x%x, value = %u\n", indirect_dev->addr_low, addr_l);
+ goto fail;
+ }
+
+ ret = wb_logic_reg_write(indirect_dev, indirect_dev->addr_high, &addr_h, WIDTH_1Byte);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_read write reg error.offset = 0x%x, value = %u\n", indirect_dev->addr_high, addr_h);
+ goto fail;
+ }
+
+ ret = wb_logic_reg_write(indirect_dev, indirect_dev->opt_ctl, &op_code, WIDTH_1Byte);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_read write reg error.offset = 0x%x, value = %u\n", indirect_dev->opt_ctl, INDIRECT_OP_READ);
+ goto fail;
+ }
+
+ ret = wb_logic_reg_read(indirect_dev, indirect_dev->rd_data, buf, rd_data_width);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_read read reg error.read offset = 0x%x\n, ret = %d", indirect_dev->rd_data, ret);
+ goto fail;
+ }
+
+ INDIRECT_DEV_DEBUG("indirect_read success, addr = 0x%x\n", address);
+ spin_unlock_irqrestore(&indirect_dev->indirect_dev_lock, flags);
+ return ret;
+fail:
+ spin_unlock_irqrestore(&indirect_dev->indirect_dev_lock, flags);
+ return ret;
+}
+
+static int device_read(struct indirect_dev_info *indirect_dev, uint32_t offset, uint8_t *buf, size_t count)
+{
+ int i, ret;
+ u32 data_width;
+ u32 tmp;
+
+ data_width = indirect_dev->data_bus_width;
+
+ if (offset % data_width) {
+ INDIRECT_DEV_ERROR("data bus width:%d, offset:0x%x, read size %zu invalid.\n",
+ data_width, offset, count);
+ return -EINVAL;
+ }
+
+ if (count > indirect_dev->indirect_len - offset) {
+ INDIRECT_DEV_DEBUG("read count out of range. input len:%zu, read len:%u.\n",
+ count, indirect_dev->indirect_len - offset);
+ count = indirect_dev->indirect_len - offset;
+ }
+ tmp = count;
+
+ for (i = 0; i < count; i += data_width) {
+ ret = indirect_addressing_read(indirect_dev, buf + i, offset + i, (tmp > data_width ? data_width : tmp));
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("read error.read offset = %u\n", (offset + i));
+ return -EFAULT;
+ }
+ tmp -= data_width;
+ }
+
+ return count;
+}
+
+static int indirect_addressing_write(struct indirect_dev_info *indirect_dev, uint8_t *buf, uint32_t address, uint32_t wr_data_width)
+{
+ uint8_t addr_l, addr_h, op_code;
+ unsigned long flags;
+ int ret = 0;
+
+ addr_h = INDIRECT_ADDR_H(address);
+ addr_l = INDIRECT_ADDR_L(address);
+ op_code = INDIRECT_OP_WRITE;
+
+ spin_lock_irqsave(&indirect_dev->indirect_dev_lock, flags);
+
+ ret = wb_logic_reg_write(indirect_dev, indirect_dev->wr_data, buf, wr_data_width);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_write read reg error.read offset = 0x%x\n, ret = %d", indirect_dev->wr_data, ret);
+ goto fail;
+ }
+
+ ret = wb_logic_reg_write(indirect_dev, indirect_dev->addr_low, &addr_l, WIDTH_1Byte);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_write write reg error.offset = 0x%x, value = %u\n", indirect_dev->addr_low, addr_l);
+ goto fail;
+ }
+
+ ret = wb_logic_reg_write(indirect_dev, indirect_dev->addr_high, &addr_h, WIDTH_1Byte);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_write write reg error.offset = 0x%x, value = %u\n", indirect_dev->addr_high, addr_h);
+ goto fail;
+ }
+
+ ret = wb_logic_reg_write(indirect_dev, indirect_dev->opt_ctl, &op_code, WIDTH_1Byte);
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("indirect_write write reg error.offset = 0x%x, value = %u\n", indirect_dev->opt_ctl, INDIRECT_OP_READ);
+ goto fail;
+ }
+
+ INDIRECT_DEV_DEBUG("indirect_write success, addr = 0x%x\n", address);
+ spin_unlock_irqrestore(&indirect_dev->indirect_dev_lock, flags);
+ return ret;
+fail:
+ spin_unlock_irqrestore(&indirect_dev->indirect_dev_lock, flags);
+ return ret;
+}
+
+static int device_write(struct indirect_dev_info *indirect_dev, uint32_t offset, uint8_t *buf, size_t count)
+{
+ int i, ret;
+ u32 data_width;
+ u32 tmp;
+
+ if (offset > indirect_dev->indirect_len) {
+ INDIRECT_DEV_DEBUG("offset: 0x%x, spi len: 0x%x, count: %zu, EOF.\n",
+ offset, indirect_dev->indirect_len, count);
+ return 0;
+ }
+
+ data_width = indirect_dev->data_bus_width;
+ if (offset % data_width) {
+ INDIRECT_DEV_ERROR("data bus width:%d, offset:0x%x, read size %zu invalid.\n",
+ data_width, offset, count);
+ return -EINVAL;
+ }
+
+ if (count > (indirect_dev->indirect_len - offset)) {
+ INDIRECT_DEV_DEBUG("write count out of range. input len:%zu, read len:%u.\n",
+ count, indirect_dev->indirect_len - offset);
+ count = indirect_dev->indirect_len - offset;
+ }
+
+ if (count == 0) {
+ INDIRECT_DEV_DEBUG("offset: 0x%x, i2c len: 0x%x, read len: %zu, EOF.\n",
+ offset, indirect_dev->indirect_len, count);
+ return 0;
+ }
+
+ tmp = count;
+ for (i = 0; i < count; i += data_width) {
+ ret = indirect_addressing_write(indirect_dev, buf + i, offset + i, (tmp > data_width ? data_width : tmp));
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("write error.offset = %u\n", (offset + i));
+ return -EFAULT;
+ }
+ tmp -= data_width;
+ }
+ return count;
+}
+
+static ssize_t indirect_dev_read(struct file *file, char __user *buf, size_t count, loff_t *offset, int flag)
+{
+ u8 val[MAX_RW_LEN];
+ int ret, read_len;
+ struct indirect_dev_info *indirect_dev;
+
+ indirect_dev = file->private_data;
+ if (indirect_dev == NULL) {
+ INDIRECT_DEV_ERROR("can't get read private_data.\n");
+ return -EINVAL;
+ }
+
+ if (count == 0) {
+ INDIRECT_DEV_ERROR("Invalid params, read count is 0.\n");
+ return -EINVAL;
+ }
+
+ if (count > sizeof(val)) {
+ INDIRECT_DEV_DEBUG("read count %zu exceed max %zu.\n", count, sizeof(val));
+ count = sizeof(val);
+ }
+
+ mem_clear(val, sizeof(val));
+ read_len = device_read(indirect_dev, (uint32_t)*offset, val, count);
+ if (read_len < 0) {
+ INDIRECT_DEV_ERROR("indirect dev read failed, dev name:%s, offset:0x%x, len:%zu.\n",
+ indirect_dev->name, (uint32_t)*offset, count);
+ return read_len;
+ }
+
+ /* check flag is user spase or kernel spase */
+ if (flag == USER_SPACE) {
+ INDIRECT_DEV_DEBUG("user space read, buf: %p, offset: %lld, read count %zu.\n",
+ buf, *offset, count);
+ if (copy_to_user(buf, val, read_len)) {
+ INDIRECT_DEV_ERROR("copy_to_user failed.\n");
+ return -EFAULT;
+ }
+ } else {
+ INDIRECT_DEV_DEBUG("kernel space read, buf: %p, offset: %lld, read count %zu.\n",
+ buf, *offset, count);
+ memcpy(buf, val, read_len);
+ }
+
+ *offset += read_len;
+ ret = read_len;
+ return ret;
+}
+
+static ssize_t indirect_dev_read_user(struct file *file, char __user *buf, size_t count, loff_t *offset)
+{
+ int ret;
+
+ INDIRECT_DEV_DEBUG("indirect_dev_read_user, file: %p, count: %lu, offset: %lld\n",
+ file, count, *offset);
+ ret = indirect_dev_read(file, buf, count, offset, USER_SPACE);
+ return ret;
+}
+
+
+static ssize_t indirect_dev_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+ int ret;
+
+ INDIRECT_DEV_DEBUG("indirect_dev_read_iter, file: %p, count: %zu, offset: %lld\n",
+ iocb->ki_filp, to->count, iocb->ki_pos);
+ ret = indirect_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPACE);
+ return ret;
+}
+
+static ssize_t indirect_dev_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset, int flag)
+{
+ u8 val[MAX_RW_LEN];
+ int write_len;
+ struct indirect_dev_info *indirect_dev;
+
+ indirect_dev = file->private_data;
+ if (indirect_dev == NULL) {
+ INDIRECT_DEV_ERROR("get write private_data error.\n");
+ return -EINVAL;
+ }
+
+ if (count == 0) {
+ INDIRECT_DEV_ERROR("Invalid params, write count is 0.\n");
+ return -EINVAL;
+ }
+
+ if (count > sizeof(val)) {
+ INDIRECT_DEV_DEBUG("write count %zu exceed max %zu.\n", count, sizeof(val));
+ count = sizeof(val);
+ }
+
+ mem_clear(val, sizeof(val));
+ /* check flag is user spase or kernel spase */
+ if (flag == USER_SPACE) {
+ INDIRECT_DEV_DEBUG("user space write, buf: %p, offset: %lld, write count %zu.\n",
+ buf, *offset, count);
+ if (copy_from_user(val, buf, count)) {
+ INDIRECT_DEV_ERROR("copy_from_user failed.\n");
+ return -EFAULT;
+ }
+ } else {
+ INDIRECT_DEV_DEBUG("kernel space write, buf: %p, offset: %lld, write count %zu.\n",
+ buf, *offset, count);
+ memcpy(val, buf, count);
+ }
+
+ write_len = device_write(indirect_dev, (uint32_t)*offset, val, count);
+ if (write_len < 0) {
+ INDIRECT_DEV_ERROR("indirect dev write failed, dev name:%s, offset:0x%llx, len:%zu.\n",
+ indirect_dev->name, *offset, count);
+ return write_len;
+ }
+
+ *offset += write_len;
+ return write_len;
+}
+
+static ssize_t indirect_dev_write_user(struct file *file, const char __user *buf, size_t count, loff_t *offset)
+{
+ int ret;
+
+ INDIRECT_DEV_DEBUG("indirect_dev_write_user, file: %p, count: %lu, offset: %lld\n",
+ file, count, *offset);
+ ret = indirect_dev_write(file, buf, count, offset, USER_SPACE);
+ return ret;
+}
+
+static ssize_t indirect_dev_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+ int ret;
+
+ INDIRECT_DEV_DEBUG("indirect_dev_write_iter, file: %p, count: %zu, offset: %lld\n",
+ iocb->ki_filp, from->count, iocb->ki_pos);
+ ret = indirect_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPACE);
+ return ret;
+}
+
+static loff_t indirect_dev_llseek(struct file *file, loff_t offset, int origin)
+{
+ loff_t ret = 0;
+ struct indirect_dev_info *indirect_dev;
+
+ indirect_dev = file->private_data;
+ if (indirect_dev == NULL) {
+ INDIRECT_DEV_ERROR("indirect_dev is NULL, llseek failed.\n");
+ return -EINVAL;
+ }
+
+ switch (origin) {
+ case SEEK_SET:
+ if (offset < 0) {
+ INDIRECT_DEV_ERROR("SEEK_SET, offset:%lld, invalid.\n", offset);
+ ret = -EINVAL;
+ break;
+ }
+ if (offset > indirect_dev->indirect_len) {
+ INDIRECT_DEV_ERROR("SEEK_SET out of range, offset:%lld, i2c_len:0x%x.\n",
+ offset, indirect_dev->indirect_len);
+ ret = - EINVAL;
+ break;
+ }
+ file->f_pos = offset;
+ ret = file->f_pos;
+ break;
+ case SEEK_CUR:
+ if (((file->f_pos + offset) > indirect_dev->indirect_len) || ((file->f_pos + offset) < 0)) {
+ INDIRECT_DEV_ERROR("SEEK_CUR out of range, f_ops:%lld, offset:%lld.\n",
+ file->f_pos, offset);
+ }
+ file->f_pos += offset;
+ ret = file->f_pos;
+ break;
+ default:
+ INDIRECT_DEV_ERROR("unsupport llseek type:%d.\n", origin);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static long indirect_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static int indirect_dev_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = iminor(inode);
+ struct indirect_dev_info *indirect_dev;
+
+ if (minor >= MAX_INDIRECT_DEV_NUM) {
+ INDIRECT_DEV_ERROR("minor out of range, minor = %d.\n", minor);
+ return -ENODEV;
+ }
+
+ indirect_dev = indirect_dev_arry[minor];
+ if (indirect_dev == NULL) {
+ INDIRECT_DEV_ERROR("indirect_dev is NULL, open failed, minor = %d\n", minor);
+ return -ENODEV;
+ }
+
+ file->private_data = indirect_dev;
+
+ return 0;
+}
+
+static int indirect_dev_release(struct inode *inode, struct file *file)
+{
+ file->private_data = NULL;
+
+ return 0;
+}
+
+static const struct file_operations indirect_dev_fops = {
+ .owner = THIS_MODULE,
+ .llseek = indirect_dev_llseek,
+ .read = indirect_dev_read_user,
+ .write = indirect_dev_write_user,
+ .read_iter = indirect_dev_read_iter,
+ .write_iter = indirect_dev_write_iter,
+ .unlocked_ioctl = indirect_dev_ioctl,
+ .open = indirect_dev_open,
+ .release = indirect_dev_release,
+};
+
+static struct indirect_dev_info *dev_match(const char *path)
+{
+ struct indirect_dev_info *indirect_dev;
+ char dev_name[DEV_NAME_LEN];
+ int i;
+
+ for (i = 0; i < MAX_INDIRECT_DEV_NUM; i++) {
+ if (indirect_dev_arry[i] == NULL) {
+ continue;
+ }
+ indirect_dev = indirect_dev_arry[i];
+ snprintf(dev_name, DEV_NAME_LEN,"/dev/%s", indirect_dev->name);
+ if (!strcmp(path, dev_name)) {
+ INDIRECT_DEV_DEBUG("get dev_name = %s, minor = %d\n", dev_name, i);
+ return indirect_dev;
+ }
+ }
+
+ return NULL;
+}
+
+int indirect_device_func_read(const char *path, uint32_t offset, uint8_t *buf, size_t count)
+{
+ struct indirect_dev_info *indirect_dev;
+ int read_len;
+
+ if (path == NULL) {
+ INDIRECT_DEV_ERROR("path NULL");
+ return -EINVAL;
+ }
+
+ if (buf == NULL) {
+ INDIRECT_DEV_ERROR("buf NULL");
+ return -EINVAL;
+ }
+
+ indirect_dev = dev_match(path);
+ if (indirect_dev == NULL) {
+ INDIRECT_DEV_ERROR("indirect_dev match failed. dev path = %s", path);
+ return -EINVAL;
+ }
+
+ read_len = device_read(indirect_dev, offset, buf, count);
+ if (read_len < 0) {
+ INDIRECT_DEV_ERROR("indirect_dev_read_tmp failed, ret:%d.\n", read_len);
+ }
+ return read_len;
+}
+EXPORT_SYMBOL(indirect_device_func_read);
+
+int indirect_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t count)
+{
+ struct indirect_dev_info *indirect_dev;
+ int write_len;
+
+ if (path == NULL) {
+ INDIRECT_DEV_ERROR("path NULL");
+ return -EINVAL;
+ }
+
+ if (buf == NULL) {
+ INDIRECT_DEV_ERROR("buf NULL");
+ return -EINVAL;
+ }
+
+ indirect_dev = dev_match(path);
+ if (indirect_dev == NULL) {
+ INDIRECT_DEV_ERROR("indirect_dev match failed. dev path = %s", path);
+ return -EINVAL;
+ }
+
+ write_len = device_write(indirect_dev, offset, buf, count);
+ if (write_len < 0) {
+ INDIRECT_DEV_ERROR("indirect_dev_write_tmp failed, ret:%d.\n", write_len);
+ }
+ return write_len;
+}
+EXPORT_SYMBOL(indirect_device_func_write);
+
+
+static int wb_indirect_dev_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct indirect_dev_info *indirect_dev;
+ struct miscdevice *misc;
+ indirect_dev_device_t *indirect_dev_device;
+
+ INDIRECT_DEV_DEBUG("wb_indirect_dev_probe\n");
+
+ indirect_dev = devm_kzalloc(&pdev->dev, sizeof(struct indirect_dev_info), GFP_KERNEL);
+ if (!indirect_dev) {
+ dev_err(&pdev->dev, "devm_kzalloc error.\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, indirect_dev);
+ indirect_dev->dev = &pdev->dev;
+
+ if (pdev->dev.of_node) {
+ ret = 0;
+ ret += of_property_read_string(pdev->dev.of_node, "dev_name", &indirect_dev->name);
+ ret += of_property_read_string(pdev->dev.of_node, "logic_dev_name", &indirect_dev->logic_dev_name);
+ ret += of_property_read_u32(pdev->dev.of_node, "addr_low", &indirect_dev->addr_low);
+ ret += of_property_read_u32(pdev->dev.of_node, "data_bus_width", &indirect_dev->data_bus_width);
+ ret += of_property_read_u32(pdev->dev.of_node, "addr_bus_width", &indirect_dev->addr_bus_width);
+ ret += of_property_read_u32(pdev->dev.of_node, "addr_high", &indirect_dev->addr_high);
+ ret += of_property_read_u32(pdev->dev.of_node, "wr_data", &indirect_dev->wr_data);
+ ret += of_property_read_u32(pdev->dev.of_node, "rd_data", &indirect_dev->rd_data);
+ ret += of_property_read_u32(pdev->dev.of_node, "opt_ctl", &indirect_dev->opt_ctl);
+ ret += of_property_read_u32(pdev->dev.of_node, "indirect_len", &indirect_dev->indirect_len);
+ ret += of_property_read_u32(pdev->dev.of_node, "logic_func_mode", &indirect_dev->logic_func_mode);
+
+ if (of_property_read_u32(pdev->dev.of_node, "wr_data_width", &indirect_dev->wr_data_width)) {
+ /* dts have no wr_data_width,set default 1 */
+ indirect_dev->wr_data_width = WIDTH_1Byte;
+ }
+ if (of_property_read_u32(pdev->dev.of_node, "rd_data_width", &indirect_dev->rd_data_width)) {
+ /* dts have no rd_data_width,set default 1 */
+ indirect_dev->rd_data_width = WIDTH_1Byte;
+ }
+ if (ret != 0) {
+ dev_err(&pdev->dev, "dts config error.ret:%d.\n", ret);
+ return -ENXIO;
+ }
+ } else {
+ if (pdev->dev.platform_data == NULL) {
+ dev_err(&pdev->dev, "Failed to get platform data config.\n");
+ return -ENXIO;
+ }
+ indirect_dev_device = pdev->dev.platform_data;
+ indirect_dev->name = indirect_dev_device->dev_name;
+ indirect_dev->logic_dev_name = indirect_dev_device->logic_dev_name;
+ indirect_dev->data_bus_width = indirect_dev_device->data_bus_width;
+ indirect_dev->addr_bus_width = indirect_dev_device->addr_bus_width;
+ indirect_dev->wr_data = indirect_dev_device->wr_data;
+ indirect_dev->wr_data_width = indirect_dev_device->wr_data_width;
+ indirect_dev->addr_low = indirect_dev_device->addr_low;
+ indirect_dev->addr_high = indirect_dev_device->addr_high;
+ indirect_dev->rd_data = indirect_dev_device->rd_data;
+ indirect_dev->rd_data_width = indirect_dev_device->rd_data_width;
+ indirect_dev->opt_ctl = indirect_dev_device->opt_ctl;
+ indirect_dev->indirect_len = indirect_dev_device->indirect_len;
+ indirect_dev->logic_func_mode = indirect_dev_device->logic_func_mode;
+ }
+
+ switch (indirect_dev->logic_func_mode) {
+ case SYMBOL_I2C_DEV_MODE:
+ indirect_dev->write_intf_addr = (unsigned long)kallsyms_lookup_name_fun("i2c_device_func_write");
+ indirect_dev->read_intf_addr = (unsigned long)kallsyms_lookup_name_fun("i2c_device_func_read");
+ break;
+ case SYMBOL_SPI_DEV_MODE:
+ indirect_dev->write_intf_addr = (unsigned long)kallsyms_lookup_name_fun("spi_device_func_write");
+ indirect_dev->read_intf_addr = (unsigned long)kallsyms_lookup_name_fun("spi_device_func_read");
+ break;
+ case SYMBOL_IO_DEV_MODE:
+ indirect_dev->write_intf_addr = (unsigned long)kallsyms_lookup_name_fun("io_device_func_write");
+ indirect_dev->read_intf_addr = (unsigned long)kallsyms_lookup_name_fun("io_device_func_read");
+ break;
+ case SYMBOL_PCIE_DEV_MODE:
+ indirect_dev->write_intf_addr = (unsigned long)kallsyms_lookup_name_fun("pcie_device_func_write");
+ indirect_dev->read_intf_addr = (unsigned long)kallsyms_lookup_name_fun("pcie_device_func_read");
+ break;
+ case FILE_MODE:
+ indirect_dev->write_intf_addr = (unsigned long)wb_dev_file_write;
+ indirect_dev->read_intf_addr = (unsigned long)wb_dev_file_read;
+ break;
+ default:
+ dev_err(&pdev->dev, "func mode %d don't support.\n", indirect_dev->logic_func_mode);
+ return -EINVAL;
+ }
+
+ if (!indirect_dev->write_intf_addr || !indirect_dev->read_intf_addr) {
+ dev_err(&pdev->dev, "Fail: func mode %u rw symbol undefined.\n", indirect_dev->logic_func_mode);
+ return -ENOSYS;
+ }
+
+ /* TODO: data_bus_width unuse now, need judge in rd or wr */
+ dev_info(&pdev->dev, "register indirect device %s success. logic_dev_name: %s, indirect_len: 0x%x, data_bus_width: 0x%x, dependent dev: 0x%x, wr_data: 0x%x, wr_data_width: %d, \
+ rd_data: 0x%x, rd_data_width: %d, addr_low: 0x%x, addr_high: 0x%x, opt_ctl: 0x%x, logic_func_mode: %d\n", indirect_dev->name, indirect_dev->logic_dev_name, indirect_dev->indirect_len, indirect_dev->data_bus_width, \
+ indirect_dev->addr_bus_width, indirect_dev->wr_data, indirect_dev->wr_data_width, indirect_dev->rd_data, indirect_dev->rd_data_width, indirect_dev->addr_low, indirect_dev->addr_high,\
+ indirect_dev->opt_ctl, indirect_dev->logic_func_mode);
+
+ misc = &indirect_dev->misc;
+ misc->minor = MISC_DYNAMIC_MINOR;
+ misc->name = indirect_dev->name;
+ misc->fops = &indirect_dev_fops;
+ misc->mode = 0666;
+ if (misc_register(misc) != 0) {
+ dev_err(&pdev->dev, "register %s faild.\n", misc->name);
+ return -ENXIO;
+ }
+
+ if (misc->minor >= MAX_INDIRECT_DEV_NUM) {
+ dev_err(&pdev->dev, "minor number beyond the limit! is %d.\n", misc->minor);
+ misc_deregister(misc);
+ return -ENXIO;
+ }
+ spin_lock_init(&indirect_dev->indirect_dev_lock);
+ indirect_dev_arry[misc->minor] = indirect_dev;
+
+ dev_info(&pdev->dev, "register indirect device %s success.\n", indirect_dev->name);
+ return 0;
+}
+
+static int wb_indirect_dev_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < MAX_INDIRECT_DEV_NUM; i++) {
+ if (indirect_dev_arry[i] != NULL) {
+ if (indirect_dev_arry[i]->dev == &pdev->dev) {
+ misc_deregister(&indirect_dev_arry[i]->misc);
+ indirect_dev_arry[i] = NULL;
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+static const struct of_device_id wb_indirect_dev_driver_of_match[] = {
+ { .compatible = "wb-indirect-dev" },
+ { },
+};
+
+static struct platform_driver wb_indirect_dev_driver = {
+ .probe = wb_indirect_dev_probe,
+ .remove = wb_indirect_dev_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MODULE_NAME,
+ .of_match_table = wb_indirect_dev_driver_of_match,
+ },
+};
+
+static int __init wb_indirect_dev_init(void)
+{
+ int ret;
+
+ ret = find_kallsyms_lookup_name();
+ if (ret < 0) {
+ INDIRECT_DEV_ERROR("find kallsyms_lookup_name failed\n");
+ return -ENXIO;
+ }
+ INDIRECT_DEV_DEBUG("find kallsyms_lookup_name ok\n");
+ return platform_driver_register(&wb_indirect_dev_driver);
+}
+
+static void __exit wb_indirect_dev_exit(void)
+{
+ platform_driver_unregister(&wb_indirect_dev_driver);
+}
+
+module_init(wb_indirect_dev_init);
+module_exit(wb_indirect_dev_exit);
+MODULE_DESCRIPTION("indirect device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("support");
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_indirect_dev.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_indirect_dev.h
new file mode 100644
index 000000000000..bc2570f52794
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_indirect_dev.h
@@ -0,0 +1,54 @@
+/*
+ * A header definition for wb_indirect_dev driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __WB_INDIRECT_DEV_H__
+#define __WB_INDIRECT_DEV_H__
+
+#include
+
+#define DEV_NAME_LEN (64)
+#define WIDTH_1Byte (1)
+#define WIDTH_2Byte (2)
+#define WIDTH_4Byte (4)
+#define MAX_RW_LEN (256)
+
+#define mem_clear(data, size) memset((data), 0, (size))
+
+typedef int (*device_func_write)(const char *, uint32_t, uint8_t *, size_t);
+typedef int (*device_func_read)(const char *, uint32_t, uint8_t *, size_t );
+
+typedef struct indirect_dev_device_s {
+ char dev_name[DEV_NAME_LEN];
+ char logic_dev_name[DEV_NAME_LEN];
+ uint32_t data_bus_width;
+ uint32_t addr_bus_width;
+ uint32_t indirect_len;
+ uint32_t wr_data;
+ uint32_t wr_data_width;
+ uint32_t addr_low;
+ uint32_t addr_high;
+ uint32_t rd_data;
+ uint32_t rd_data_width;
+ uint32_t opt_ctl;
+ uint32_t logic_func_mode;
+ int device_flag;
+} indirect_dev_device_t;
+
+#endif /* __WB_INDIRECT_DEV_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.c
index 03571871014b..6699397aa4b2 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.c
@@ -1,7 +1,23 @@
/*
- * wb_io_dev.c
- * ko to read/write ioports through /dev/XXX device
+ * An wb_io_dev driver for read/write ioports device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include
#include
#include
@@ -27,8 +43,8 @@
#define IO_INDIRECT_OP_WRITE (0x2)
#define IO_INDIRECT_OP_READ (0X3)
-#define KERNEL_SPASE (0)
-#define USER_SPASE (1)
+#define KERNEL_SPACE (0)
+#define USER_SPACE (1)
static int g_io_dev_debug = 0;
static int g_io_dev_error = 0;
@@ -54,9 +70,11 @@ typedef struct wb_io_dev_s {
uint32_t io_len;
uint32_t indirect_addr;
uint32_t wr_data;
+ uint32_t wr_data_width;
uint32_t addr_low;
uint32_t addr_high;
uint32_t rd_data;
+ uint32_t rd_data_width;
uint32_t opt_ctl;
spinlock_t io_dev_lock;
struct miscdevice misc;
@@ -90,14 +108,15 @@ static int io_dev_release(struct inode *inode, struct file *file)
return 0;
}
-uint8_t io_indirect_addressing_read(wb_io_dev_t *wb_io_dev, uint32_t address)
+u32 io_indirect_addressing_read(wb_io_dev_t *wb_io_dev, uint32_t address)
{
- uint8_t addr_l, addr_h, value;
+ int width;
+ uint8_t addr_l, addr_h;
unsigned long flags;
+ u32 value;
addr_h = IO_INDIRECT_ADDR_H(address);
addr_l = IO_INDIRECT_ADDR_L(address);
- IO_DEV_DEBUG_VERBOSE("read one count, addr = 0x%x\n", address);
spin_lock_irqsave(&wb_io_dev->io_dev_lock, flags);
@@ -107,16 +126,32 @@ uint8_t io_indirect_addressing_read(wb_io_dev_t *wb_io_dev, uint32_t address)
outb(IO_INDIRECT_OP_READ, wb_io_dev->io_base + wb_io_dev->opt_ctl);
- value = inb(wb_io_dev->io_base + wb_io_dev->rd_data);
+ width = wb_io_dev->rd_data_width;
+ switch (width) {
+ case IO_DATA_WIDTH_2:
+ value = inw(wb_io_dev->io_base + wb_io_dev->rd_data);
+ break;
+ case IO_DATA_WIDTH_4:
+ value = inl(wb_io_dev->io_base + wb_io_dev->rd_data);
+ break;
+ case IO_DATA_WIDTH_1:
+ default:
+ /* default 1 byte mode */
+ value = inb(wb_io_dev->io_base + wb_io_dev->rd_data);
+ break;
+ }
spin_unlock_irqrestore(&wb_io_dev->io_dev_lock, flags);
+ IO_DEV_DEBUG_VERBOSE("read one count, addr = 0x%x, value = 0x%x\n", address, value);
+
return value;
}
static int io_dev_read_tmp(wb_io_dev_t *wb_io_dev, uint32_t offset, uint8_t *buf, size_t count)
{
- int i;
+ int width, i, j;
+ u32 val;
if (offset > wb_io_dev->io_len) {
IO_DEV_DEBUG_VERBOSE("offset:0x%x, io len:0x%x, EOF.\n", offset, wb_io_dev->io_len);
@@ -129,8 +164,19 @@ static int io_dev_read_tmp(wb_io_dev_t *wb_io_dev, uint32_t offset, uint8_t *buf
count = wb_io_dev->io_len - offset;
}
if (wb_io_dev->indirect_addr) {
- for (i = 0; i < count; i++) {
- buf[i] = io_indirect_addressing_read(wb_io_dev, offset + i);
+ width = wb_io_dev->rd_data_width;
+
+ if (offset % width) {
+ IO_DEV_DEBUG_VERBOSE("rd_data_width:%d, offset:0x%x, size %lu invalid.\n",
+ width, offset, count);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < count; i += width) {
+ val = io_indirect_addressing_read(wb_io_dev, offset + i);
+ for (j = 0; (j < width) && (i + j < count); j++) {
+ buf[i + j] = (val >> (8 * j)) & 0xff;
+ }
}
} else {
for (i = 0; i < count; i++) {
@@ -171,7 +217,7 @@ static ssize_t io_dev_read(struct file *file, char __user *buf, size_t count, lo
}
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
IO_DEV_DEBUG_VERBOSE("user space read, buf: %p, offset: %lld, read count %lu.\n",
buf, *offset, count);
if (copy_to_user(buf, buf_tmp, read_len)) {
@@ -194,7 +240,7 @@ static ssize_t io_dev_read_user(struct file *file, char __user *buf, size_t coun
IO_DEV_DEBUG_VERBOSE("io_dev_read_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = io_dev_read(file, buf, count, offset, USER_SPASE);
+ ret = io_dev_read(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -204,22 +250,37 @@ static ssize_t io_dev_read_iter(struct kiocb *iocb, struct iov_iter *to)
IO_DEV_DEBUG_VERBOSE("io_dev_read_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, to->count, iocb->ki_pos);
- ret = io_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = io_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
-void io_indirect_addressing_write(wb_io_dev_t *wb_io_dev, uint32_t address, uint8_t reg_val)
+void io_indirect_addressing_write(wb_io_dev_t *wb_io_dev, uint32_t address, u32 reg_val)
{
+ int width;
uint8_t addr_l, addr_h;
unsigned long flags;
addr_h = IO_INDIRECT_ADDR_H(address);
addr_l = IO_INDIRECT_ADDR_L(address);
- IO_DEV_DEBUG_VERBOSE("write one count, addr = 0x%x\n", address);
+ IO_DEV_DEBUG_VERBOSE("write one count, addr = 0x%x, val = 0x%x\n", address, reg_val);
+
+ width = wb_io_dev->wr_data_width;
spin_lock_irqsave(&wb_io_dev->io_dev_lock, flags);
- outb(reg_val, wb_io_dev->io_base + wb_io_dev->wr_data);
+ switch (width) {
+ case IO_DATA_WIDTH_2:
+ outw(reg_val, wb_io_dev->io_base + wb_io_dev->wr_data);
+ break;
+ case IO_DATA_WIDTH_4:
+ outl(reg_val, wb_io_dev->io_base + wb_io_dev->wr_data);
+ break;
+ case IO_DATA_WIDTH_1:
+ default:
+ /* default 1 byte mode */
+ outb(reg_val, wb_io_dev->io_base + wb_io_dev->wr_data);
+ break;
+ }
outb(addr_l, wb_io_dev->io_base + wb_io_dev->addr_low);
@@ -234,7 +295,8 @@ void io_indirect_addressing_write(wb_io_dev_t *wb_io_dev, uint32_t address, uint
static int io_dev_write_tmp(wb_io_dev_t *wb_io_dev, uint32_t offset, uint8_t *buf, size_t count)
{
- int i;
+ int width, i, j;
+ u32 val;
if (offset > wb_io_dev->io_len) {
IO_DEV_DEBUG_VERBOSE("offset:0x%x, io len:0x%x, EOF.\n", offset, wb_io_dev->io_len);
@@ -247,8 +309,20 @@ static int io_dev_write_tmp(wb_io_dev_t *wb_io_dev, uint32_t offset, uint8_t *bu
count = wb_io_dev->io_len - offset;
}
if (wb_io_dev->indirect_addr) {
- for (i = 0; i < count; i++) {
- io_indirect_addressing_write(wb_io_dev, offset + i, buf[i]);
+ width = wb_io_dev->wr_data_width;
+
+ if (offset % width) {
+ IO_DEV_DEBUG_VERBOSE("wr_data_width:%d, offset:0x%x, size %lu invalid.\n",
+ width, offset, count);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < count; i += width) {
+ val = 0;
+ for (j = 0; (j < width) && (i + j < count); j++) {
+ val |= buf[i + j] << (8 * j);
+ }
+ io_indirect_addressing_write(wb_io_dev, i + offset, val);
}
} else {
for (i = 0; i < count; i++) {
@@ -283,7 +357,7 @@ static ssize_t io_dev_write(struct file *file, const char __user *buf, size_t co
mem_clear(buf_tmp, sizeof(buf_tmp));
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
IO_DEV_DEBUG_VERBOSE("user space write, buf: %p, offset: %lld, write count %lu.\n",
buf, *offset, count);
if (copy_from_user(buf_tmp, buf, count)) {
@@ -312,7 +386,7 @@ static ssize_t io_dev_write_user(struct file *file, const char __user *buf, size
IO_DEV_DEBUG_VERBOSE("io_dev_write_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = io_dev_write(file, buf, count, offset, USER_SPASE);
+ ret = io_dev_write(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -322,7 +396,7 @@ static ssize_t io_dev_write_iter(struct kiocb *iocb, struct iov_iter *from)
IO_DEV_DEBUG_VERBOSE("io_dev_write_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, from->count, iocb->ki_pos);
- ret = io_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = io_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
@@ -455,7 +529,7 @@ int io_device_func_write(const char *path, uint32_t offset, uint8_t *buf, size_t
wb_io_dev = dev_match(path);
if (wb_io_dev == NULL) {
- IO_DEV_DEBUG_ERROR("i2c_dev match failed. dev path = %s", path);
+ IO_DEV_DEBUG_ERROR("io_dev match failed. dev path = %s", path);
return -EINVAL;
}
@@ -488,15 +562,22 @@ static int io_dev_probe(struct platform_device *pdev)
ret += of_property_read_u32(pdev->dev.of_node, "io_base", &wb_io_dev->io_base);
ret += of_property_read_u32(pdev->dev.of_node, "io_len", &wb_io_dev->io_len);
if (of_property_read_bool(pdev->dev.of_node, "indirect_addr")) {
-
wb_io_dev->indirect_addr = 1;
ret += of_property_read_u32(pdev->dev.of_node, "wr_data", &wb_io_dev->wr_data);
ret += of_property_read_u32(pdev->dev.of_node, "addr_low", &wb_io_dev->addr_low);
ret += of_property_read_u32(pdev->dev.of_node, "addr_high", &wb_io_dev->addr_high);
ret += of_property_read_u32(pdev->dev.of_node, "rd_data", &wb_io_dev->rd_data);
ret += of_property_read_u32(pdev->dev.of_node, "opt_ctl", &wb_io_dev->opt_ctl);
- } else {
+ if (of_property_read_u32(pdev->dev.of_node, "wr_data_width", &wb_io_dev->wr_data_width)) {
+ /* dts have no wr_data_width,set default 1 */
+ wb_io_dev->wr_data_width = IO_DATA_WIDTH_1;
+ }
+ if (of_property_read_u32(pdev->dev.of_node, "rd_data_width", &wb_io_dev->rd_data_width)) {
+ /* dts have no rd_data_width,set default 1 */
+ wb_io_dev->rd_data_width = IO_DATA_WIDTH_1;
+ }
+ } else {
wb_io_dev->indirect_addr = 0;
}
if (ret != 0) {
@@ -515,10 +596,18 @@ static int io_dev_probe(struct platform_device *pdev)
wb_io_dev->indirect_addr = io_dev_device->indirect_addr;
if (wb_io_dev->indirect_addr == 1) {
wb_io_dev->wr_data = io_dev_device->wr_data;
+ wb_io_dev->wr_data_width = io_dev_device->wr_data_width;
wb_io_dev->addr_low = io_dev_device->addr_low;
wb_io_dev->addr_high = io_dev_device->addr_high;
wb_io_dev->rd_data = io_dev_device->rd_data;
+ wb_io_dev->rd_data_width = io_dev_device->rd_data_width;
wb_io_dev->opt_ctl = io_dev_device->opt_ctl;
+ if (wb_io_dev->wr_data_width == 0) {
+ wb_io_dev->wr_data_width = IO_DATA_WIDTH_1;
+ }
+ if (wb_io_dev->rd_data_width == 0) {
+ wb_io_dev->rd_data_width = IO_DATA_WIDTH_1;
+ }
}
}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.h
index 3a1a10f0f20c..61cba26a155c 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_io_dev.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_io_dev driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_IO_DEV_H__
#define __WB_IO_DEV_H__
#include
@@ -5,15 +25,21 @@
#define mem_clear(data, size) memset((data), 0, (size))
#define IO_DEV_NAME_MAX_LEN (64)
+#define IO_DATA_WIDTH_1 (1)
+#define IO_DATA_WIDTH_2 (2)
+#define IO_DATA_WIDTH_4 (4)
+
typedef struct io_dev_device_s {
char io_dev_name[IO_DEV_NAME_MAX_LEN];
uint32_t io_base;
uint32_t io_len;
uint32_t indirect_addr;
uint32_t wr_data;
+ uint32_t wr_data_width;
uint32_t addr_low;
uint32_t addr_high;
uint32_t rd_data;
+ uint32_t rd_data_width;
uint32_t opt_ctl;
int device_flag;
} io_dev_device_t;
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.c
index c079dc409696..45290ca843ea 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.c
@@ -1,7 +1,23 @@
/*
- * wb_lpc_drv.c
- * ko to set lpc pcie config io addr and enable lpc
+ * An wb_lpc_drv driver for lpc device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.h
index 76e8c32c12e9..52c64b187bd5 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_lpc_drv.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_lpc_drv driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_LPC_DRV_H__
#define __WB_LPC_DRV_H__
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mac_bsc.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mac_bsc.c
index a94ae020a4b7..ba9cd692f8e8 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mac_bsc.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mac_bsc.c
@@ -1,6 +1,7 @@
/*
+ * An wb_mac_bsc driver for mac bsc function
*
- * Copyright (c) 1998, 1999 Frodo Looijaard
+ * Copyright (C) 2024 Micas Networks 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
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mdio_gpio_device.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mdio_gpio_device.c
index e3198b378a20..65b8d2a42749 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mdio_gpio_device.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_mdio_gpio_device.c
@@ -1,3 +1,23 @@
+/*
+ * An wb_mdio_gpio_device driver for mdio gpio device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.c
index 093d070fd429..83904d7960e0 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.c
@@ -1,7 +1,23 @@
/*
- * wb_pcie_dev.c
- * ko to read/write pcie iomem and ioports through /dev/XXX device
+ * An wb_pcie_dev driver for pcie device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include
#include
#include
@@ -25,8 +41,14 @@
#define PCIE_BUS_WIDTH_2 (2)
#define PCIE_BUS_WIDTH_4 (4)
-#define KERNEL_SPASE (0)
-#define USER_SPASE (1)
+#define KERNEL_SPACE (0)
+#define USER_SPACE (1)
+
+#define SEARCH_DEV_DEFAULT (0)
+#define SEARCH_DEV_BY_BRIDGE (1)
+
+#define SECBUS (0x19)
+#define SUBBUS (0x1a)
static int g_pcie_dev_debug = 0;
static int g_pcie_dev_error = 0;
@@ -65,6 +87,10 @@ typedef struct wb_pci_dev_s {
uint32_t bus_width;
uint32_t check_pci_id;
uint32_t pci_id;
+ uint32_t search_mode;
+ uint32_t bridge_bus;
+ uint32_t bridge_slot;
+ uint32_t bridge_fn;
struct miscdevice misc;
void (*setreg)(struct wb_pci_dev_s *wb_pci_dev, int reg, u32 value);
u32 (*getreg)(struct wb_pci_dev_s *wb_pci_dev, int reg);
@@ -250,7 +276,7 @@ static ssize_t pci_dev_read(struct file *file, char __user *buf, size_t count, l
return read_len;
}
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
PCIE_DEV_DEBUG_VERBOSE("user space read, buf: %p, offset: %lld, read count %lu.\n",
buf, *offset, count);
if (copy_to_user(buf, buf_tmp, read_len)) {
@@ -273,7 +299,7 @@ static ssize_t pci_dev_read_user(struct file *file, char __user *buf, size_t cou
PCIE_DEV_DEBUG_VERBOSE("pci_dev_read_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = pci_dev_read(file, buf, count, offset, USER_SPASE);
+ ret = pci_dev_read(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -283,7 +309,7 @@ static ssize_t pci_dev_read_iter(struct kiocb *iocb, struct iov_iter *to)
PCIE_DEV_DEBUG_VERBOSE("pci_dev_read_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, to->count, iocb->ki_pos);
- ret = pci_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = pci_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
@@ -347,7 +373,7 @@ static ssize_t pci_dev_write(struct file *file, const char __user *buf, size_t c
mem_clear(buf_tmp, sizeof(buf_tmp));
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
PCIE_DEV_DEBUG_VERBOSE("user space write, buf: %p, offset: %lld, write count %lu.\n",
buf, *offset, count);
if (copy_from_user(buf_tmp, buf, count)) {
@@ -376,7 +402,7 @@ static ssize_t pci_dev_write_user(struct file *file, const char __user *buf, siz
PCIE_DEV_DEBUG_VERBOSE("pci_dev_write_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = pci_dev_write(file, buf, count, offset, USER_SPASE);
+ ret = pci_dev_write(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -386,7 +412,7 @@ static ssize_t pci_dev_write_iter(struct kiocb *iocb, struct iov_iter *from)
PCIE_DEV_DEBUG_VERBOSE("pci_dev_write_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, from->count, iocb->ki_pos);
- ret = pci_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = pci_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
@@ -618,10 +644,11 @@ static int pci_dev_probe(struct platform_device *pdev)
int ret, devfn;
uint32_t pci_id;
wb_pci_dev_t *wb_pci_dev;
- struct pci_dev *pci_dev;
+ struct pci_dev *pci_dev, *pci_bridge_dev;
struct miscdevice *misc;
firmware_upg_t *firmware_upg;
pci_dev_device_t *pci_dev_device;
+ u8 secbus_val, subbus_val;
wb_pci_dev = devm_kzalloc(&pdev->dev, sizeof(wb_pci_dev_t), GFP_KERNEL);
if (!wb_pci_dev) {
@@ -636,7 +663,6 @@ static int pci_dev_probe(struct platform_device *pdev)
ret = 0;
ret += of_property_read_string(pdev->dev.of_node, "pci_dev_name", &wb_pci_dev->name);
ret += of_property_read_u32(pdev->dev.of_node, "pci_domain", &wb_pci_dev->domain);
- ret += of_property_read_u32(pdev->dev.of_node, "pci_bus", &wb_pci_dev->bus);
ret += of_property_read_u32(pdev->dev.of_node, "pci_slot", &wb_pci_dev->slot);
ret += of_property_read_u32(pdev->dev.of_node, "pci_fn", &wb_pci_dev->fn);
ret += of_property_read_u32(pdev->dev.of_node, "pci_bar", &wb_pci_dev->bar);
@@ -647,6 +673,30 @@ static int pci_dev_probe(struct platform_device *pdev)
return -ENXIO;
}
+ wb_pci_dev->search_mode = SEARCH_DEV_DEFAULT;
+ of_property_read_u32(pdev->dev.of_node, "search_mode", &wb_pci_dev->search_mode);
+ ret = 0;
+ if (wb_pci_dev->search_mode == SEARCH_DEV_BY_BRIDGE) {
+ ret += of_property_read_u32(pdev->dev.of_node, "bridge_bus", &wb_pci_dev->bridge_bus);
+ ret += of_property_read_u32(pdev->dev.of_node, "bridge_slot", &wb_pci_dev->bridge_slot);
+ ret += of_property_read_u32(pdev->dev.of_node, "bridge_fn", &wb_pci_dev->bridge_fn);
+ if (ret != 0) {
+ PCIE_DEV_DEBUG_VERBOSE("get pci bridge config fail, ret:%d.\n", ret);
+ return -ENXIO;
+ } else {
+ PCIE_DEV_DEBUG_VERBOSE("bridge_bus:0x%02x, bridge_slot:0x%02x, bridge_fn:0x%02x.\n",
+ wb_pci_dev->bridge_bus, wb_pci_dev->bridge_slot, wb_pci_dev->bridge_fn);
+ }
+ } else {
+ ret += of_property_read_u32(pdev->dev.of_node, "pci_bus", &wb_pci_dev->bus);
+ if (ret != 0) {
+ PCIE_DEV_DEBUG_VERBOSE("get pci bus config fail, ret:%d.\n", ret);
+ return -ENXIO;
+ } else {
+ PCIE_DEV_DEBUG_VERBOSE("get pci_bus:0x%02x.\n", wb_pci_dev->bus);
+ }
+ }
+
ret = 0;
ret += of_property_read_u32(pdev->dev.of_node, "upg_ctrl_base", &firmware_upg->upg_ctrl_base);
ret += of_property_read_u32(pdev->dev.of_node, "upg_flash_base", &firmware_upg->upg_flash_base);
@@ -674,31 +724,79 @@ static int pci_dev_probe(struct platform_device *pdev)
pci_dev_device = pdev->dev.platform_data;
wb_pci_dev->name = pci_dev_device->pci_dev_name;
wb_pci_dev->domain = pci_dev_device->pci_domain;
- wb_pci_dev->bus = pci_dev_device->pci_bus;
wb_pci_dev->slot = pci_dev_device->pci_slot;
wb_pci_dev->fn = pci_dev_device->pci_fn;
wb_pci_dev->bar = pci_dev_device->pci_bar;
wb_pci_dev->bus_width = pci_dev_device->bus_width;
wb_pci_dev->check_pci_id = pci_dev_device->check_pci_id;
- wb_pci_dev->pci_id = pci_dev_device->pci_id;
+ wb_pci_dev->search_mode = pci_dev_device->search_mode;
firmware_upg->upg_ctrl_base = pci_dev_device->upg_ctrl_base;
firmware_upg->upg_flash_base = pci_dev_device->upg_flash_base;
+ if (wb_pci_dev->search_mode == SEARCH_DEV_BY_BRIDGE) {
+ PCIE_DEV_DEBUG_VERBOSE("bridge_bus:0x%02x, bridge_slot:0x%02x, bridge_fn:0x%02x.\n",
+ wb_pci_dev->bridge_bus, wb_pci_dev->bridge_slot, wb_pci_dev->bridge_fn);
+ }
PCIE_DEV_DEBUG_VERBOSE("upg_ctrl_base:0x%04x, upg_flash_base:0x%02x.\n",
firmware_upg->upg_ctrl_base, firmware_upg->upg_flash_base);
}
- PCIE_DEV_DEBUG_VERBOSE("name:%s, domain:0x%04x, bus:0x%02x, slot:0x%02x, fn:%u, bar:%u, bus_width:%d.\n",
+ PCIE_DEV_DEBUG_VERBOSE("name:%s, domain:0x%04x, bus:0x%02x, slot:0x%02x, fn:%u, bar:%u, bus_width:%d, search_mode:%d \n",
wb_pci_dev->name, wb_pci_dev->domain, wb_pci_dev->bus, wb_pci_dev->slot, wb_pci_dev->fn,
- wb_pci_dev->bar, wb_pci_dev->bus_width);
+ wb_pci_dev->bar, wb_pci_dev->bus_width, wb_pci_dev->search_mode);
- devfn = PCI_DEVFN(wb_pci_dev->slot, wb_pci_dev->fn);
- pci_dev = pci_get_domain_bus_and_slot(wb_pci_dev->domain, wb_pci_dev->bus, devfn);
- if (pci_dev == NULL) {
- dev_err(&pdev->dev, "Failed to find pci_dev, domain:0x%04x, bus:0x%02x, devfn:0x%x\n",
- wb_pci_dev->domain, wb_pci_dev->bus, devfn);
- return -ENXIO;
+ if (wb_pci_dev->search_mode != SEARCH_DEV_DEFAULT && wb_pci_dev->search_mode != SEARCH_DEV_BY_BRIDGE) {
+ dev_err(&pdev->dev, "Error: unsupported search_mode (%d).\n", wb_pci_dev->search_mode);
+ return -EINVAL;
+ }
+
+ if (wb_pci_dev->search_mode == SEARCH_DEV_DEFAULT) {
+ wb_pci_dev->bus = pci_dev_device->pci_bus;
+ devfn = PCI_DEVFN(wb_pci_dev->slot, wb_pci_dev->fn);
+ pci_dev = pci_get_domain_bus_and_slot(wb_pci_dev->domain, wb_pci_dev->bus, devfn);
+ if (pci_dev == NULL) {
+ dev_err(&pdev->dev, "Failed to find pci_dev, domain:0x%04x, bus:0x%02x, devfn:0x%x\n",
+ wb_pci_dev->domain, wb_pci_dev->bus, devfn);
+ return -ENXIO;
+ }
+ } else { /* search_mode = SEARCH_DEV_BY_BRIDGE */
+ wb_pci_dev->bridge_bus = pci_dev_device->bridge_bus;
+ wb_pci_dev->bridge_slot = pci_dev_device->bridge_slot;
+ wb_pci_dev->bridge_fn = pci_dev_device->bridge_fn;
+ devfn = PCI_DEVFN(wb_pci_dev->bridge_slot, wb_pci_dev->bridge_fn);
+ pci_bridge_dev = pci_get_domain_bus_and_slot(wb_pci_dev->domain, wb_pci_dev->bridge_bus, devfn);
+ if (pci_bridge_dev == NULL) {
+ dev_err(&pdev->dev, "Failed to find pci_bridge_dev, domain:0x%04x, bus:0x%02x, devfn:0x%x\n",
+ wb_pci_dev->domain, wb_pci_dev->bridge_bus, devfn);
+ return -ENXIO;
+ }
+
+ ret = pci_read_config_byte(pci_bridge_dev, SECBUS, &secbus_val);
+ if (ret) {
+ PCIE_DEV_DEBUG_ERROR("pci_read_config_dword failed reg:%02x ret %d.\n", SECBUS, ret);
+ return -EIO;
+ }
+ ret = pci_read_config_byte(pci_bridge_dev, SUBBUS, &subbus_val);
+ if (ret) {
+ PCIE_DEV_DEBUG_ERROR("pci_read_config_dword failed reg:%02x ret %d.\n", SUBBUS, ret);
+ return -EIO;
+ }
+ if (secbus_val != subbus_val) {
+ /* If the SECBUS register value is different from the SUBBUS register value, a multistage PCIE bridge is available*/
+ PCIE_DEV_DEBUG_ERROR("not support ,secbus_val not equal subbus_val secbus_val:%02x secbus_val:%02x.\n", secbus_val, subbus_val);
+ return -EIO;
+ }
+ wb_pci_dev->bus = secbus_val;
+ devfn = PCI_DEVFN(wb_pci_dev->slot, wb_pci_dev->fn);
+ pci_dev = pci_get_domain_bus_and_slot(wb_pci_dev->domain, wb_pci_dev->bus, devfn);
+ if (pci_dev == NULL) {
+ dev_err(&pdev->dev, "Failed to find pci_dev, domain:0x%04x, bus:0x%02x, devfn:0x%x\n",
+ wb_pci_dev->domain, wb_pci_dev->bus, devfn);
+ return -ENXIO;
+ }
}
+
if (wb_pci_dev->check_pci_id == 1) {
+ wb_pci_dev->pci_id = pci_dev_device->pci_id;
pci_id = (pci_dev->vendor << 16) | pci_dev->device;
if (wb_pci_dev->pci_id != pci_id) {
dev_err(&pdev->dev, "Failed to check pci id, except: 0x%x, really: 0x%x\n",
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.h
index 33da8d475f91..ef390a1585f3 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_pcie_dev.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_pcie_dev driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_PCIE_DEV_H__
#define __WB_PCIE_DEV_H__
#include
@@ -23,6 +43,10 @@ typedef struct pci_dev_device_s {
int upg_ctrl_base;
int upg_flash_base;
int device_flag;
+ int search_mode;
+ int bridge_bus;
+ int bridge_slot;
+ int bridge_fn;
} pci_dev_device_t;
#endif
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.c
index 092c99da2ad8..678a48483bd7 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.c
@@ -1,3 +1,23 @@
+/*
+ * An wb_platform_i2c_dev driver for i2c platform device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include
#include
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.h
index b5158c9fec57..f40282176484 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_platform_i2c_dev.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_platform_i2c_dev driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_PLATFORM_I2C_DEV_H__
#define __WB_PLATFORM_I2C_DEV_H__
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.c
index d70424afb0e7..dd13fe9a991b 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.c
@@ -1,6 +1,21 @@
/*
- * wb_spi_dev.c
- * ko to read/write spi device through /dev/XXX device
+ * An wb_spi_dev driver for spi device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include
@@ -32,8 +47,8 @@
#define OP_READ (0x3)
#define OP_WRITE (0x2)
-#define KERNEL_SPASE (0)
-#define USER_SPASE (1)
+#define KERNEL_SPACE (0)
+#define USER_SPACE (1)
static int g_spi_dev_debug = 0;
static int g_spi_dev_error = 0;
@@ -346,7 +361,7 @@ static ssize_t spi_dev_read(struct file *file, char __user *buf, size_t count, l
}
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
SPI_DEV_DEBUG("user space read, buf: %p, offset: %lld, read count %lu.\n",
buf, *offset, count);
if (copy_to_user(buf, val, read_len)) {
@@ -370,7 +385,7 @@ static ssize_t spi_dev_read_user(struct file *file, char __user *buf, size_t cou
SPI_DEV_DEBUG("spi_dev_read_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = spi_dev_read(file, buf, count, offset, USER_SPASE);
+ ret = spi_dev_read(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -380,7 +395,7 @@ static ssize_t spi_dev_read_iter(struct kiocb *iocb, struct iov_iter *to)
SPI_DEV_DEBUG("spi_dev_read_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, to->count, iocb->ki_pos);
- ret = spi_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = spi_dev_read(iocb->ki_filp, to->kvec->iov_base, to->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
@@ -409,7 +424,7 @@ static ssize_t spi_dev_write(struct file *file, const char __user *buf,
mem_clear(val, sizeof(val));
/* check flag is user spase or kernel spase */
- if (flag == USER_SPASE) {
+ if (flag == USER_SPACE) {
SPI_DEV_DEBUG("user space write, buf: %p, offset: %lld, write count %lu.\n",
buf, *offset, count);
if (copy_from_user(val, buf, count)) {
@@ -439,7 +454,7 @@ static ssize_t spi_dev_write_user(struct file *file, const char __user *buf, siz
SPI_DEV_DEBUG("spi_dev_write_user, file: %p, count: %lu, offset: %lld\n",
file, count, *offset);
- ret = spi_dev_write(file, buf, count, offset, USER_SPASE);
+ ret = spi_dev_write(file, buf, count, offset, USER_SPACE);
return ret;
}
@@ -449,7 +464,7 @@ static ssize_t spi_dev_write_iter(struct kiocb *iocb, struct iov_iter *from)
SPI_DEV_DEBUG("spi_dev_write_iter, file: %p, count: %lu, offset: %lld\n",
iocb->ki_filp, from->count, iocb->ki_pos);
- ret = spi_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPASE);
+ ret = spi_dev_write(iocb->ki_filp, from->kvec->iov_base, from->count, &iocb->ki_pos, KERNEL_SPACE);
return ret;
}
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.h b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.h
index fed5237e3860..03ff8f42f7ec 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.h
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_dev.h
@@ -1,3 +1,23 @@
+/*
+ * A header definition for wb_spi_dev driver
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef __WB_SPI_DEV_H__
#define __WB_SPI_DEV_H__
#include
diff --git a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_gpio_device.c b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_gpio_device.c
index b073dac08a8a..61551a33d3c1 100644
--- a/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_gpio_device.c
+++ b/platform/broadcom/sonic-platform-modules-micas/common/modules/wb_spi_gpio_device.c
@@ -1,3 +1,23 @@
+/*
+ * An wb_spi_gpio_device driver for spi gpio device function
+ *
+ * Copyright (C) 2024 Micas Networks 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#include